Scrupulous add message php. PHP-Swagger Request Parameters

Scrupulous add message php.  PHP-Swagger Request Parameters
Scrupulous add message php. PHP-Swagger Request Parameters

In my Zend application, I am writing some APIs for mobile applications. To make it easier for mobile developers, I use Swagger. Everything is working fine so far, except for one GET request.

When do I call /user/messages/(sessionToken)? NumMessages = (numMessages) & pageNr = (pageNr) in the browser, I get the results I want, but when I try to let Swagger make this request, only the sessionToken is passed. I tried these annotations for Swagger:

/** * @SWG\Api(path="/user/messages/(sessionToken)?numMessages=(numMessages)&pageNr=(pageNr)", * @SWG\Operation(* method="GET", * summary=" Gets messages paged", * notes="", * type="string", * nickname="getUsermessagesPaged", * authorizations=(), * @SWG\Parameter(* name="sessionToken", * description="The token from an active user session", * required=true, * type="string", * paramType="path", * allowMultiple=true *), * @SWG\Parameter(* name="numMessages", * description=" number of messages on page (numMessages & pageNr are ignored if not both are set)", * required=true, * type="string", * paramType="query", * allowMultiple=true *), * @SWG\Parameter (* name="pageNr", * description="pagenumber (numMessages & pageNr are ignored if not both are set)", * required=true, * type="string", * paramType="query", * allowMultiple=true *), * @SWG\ResponseMessage(code=200, message="json (messages => "user_messages")"), * @SWG\ResponseMessage(code=400, message="json with error "not logged in"" ) *) *) */

Does anyone see my mistake?

Any help is welcome.

Sincerely

Update. As suggested, I changed both paramTypes to "query" and changed the path:

@SWG\Api(path="/user/messages/(sessionToken)",

but he did not work as a fighter.

xdebug in eclipse PDT shows:

RequestURI => /ias/public/user/messages/(sessionToken)

QueryParams => Zend\\Stdlib\\Parameters - *ArrayObject*storage => Array - =>

json swagger:

( "apiVersion": "1.0.0", "swaggerVersion": "1.2", "apis": [ ( "path": "\/user", "description": "Operations about users" ) ], "info" : ( "title": "Mobile access api", "description": "This is the xxx mobile access api.", "termsOfServiceUrl": null, "contact": "xxx", "license": null, "licenseUrl" : null, "_partialId": null, "_partials": , "_context": ( "comment": "\/**\ * @SWG\\Info(\ * title="Mobile access api",\ * description="This is the xxx mobile access api.",\ * contact="xxx",\ *)\ *\/", "line": 3 } } } !}

Here is the /user output:

( "basePath": "http://localhost/ias/public", "swaggerVersion": "1.2", "apiVersion": "1.0.0", "resourcePath": "/user", "apis": [ ( "path": "/user/balance/(sessionToken)", "operations": [ ( "method": "GET", "summary": "Gets userbalance", "nickname": "getUserdata", "type": "string", "parameters": [ ( "paramType": "path", "name": "sessionToken", "type": "string", "required": true, "allowMultiple": false, "description": "The token from an active user session" ) ], "responseMessages": [ ( "code": 200, "message": "json (balance => "user_balance")" ), ( "code": 400, "message ": "json with error "not logged in"" ) ], "notes": "", "authorizations": () ) ] ), ( "path": "/user/login", "operations": [ ( "method": "POST", "summary": "Logs user into the system", "nickname": "loginUser", "type": "string", "parameters": [ ( "paramType": "form", "name": "email", "type": "string", "required": true, "allowMultiple": false, "description": "The user email for login" ), ( "paramType": "form", "name": "password", "type": "string", "required": true, "allowMultiple": false, "description": "The password for login in clear text" ) ], "responseMessages": [ ( "code": 200, "message": "json with session_id, user_id, user_balance" ), ( "code": 400, "message": "json with error "no user with given email and password"" ), ( " code": 400, "message": "json with error "invalid input"" ), ( "code": 400, "message": "json with error "no post request"" ) ], "notes": "" , "authorizations": () ) ] ), ( "path": "/user/logout", "operations": [ ( "method": "POST", "summary": "Logs user out", "nickname" : "logoutUser", "type": "string", "parameters": [ ( "paramType": "form", "name": "sessionToken", "type": "string", "required": true, " allowMultiple": false, "description": "The token from an active user session" ) ], "responseMessages": [ ( "code": 200, "message": "json (result => "deleted")" ), ( "code": 400, "message": "json with error "no user_session with given sid"" ), ( "code": 400, "message": "json with error "invalid input"" ), ( "code ": 400, "message": "json with error "no post request"" ) ], "notes": "", "authorizations": () ) ] ), ( "path": "/user/messages/( sessionToken)", "operations": [ ( "method": "GET", "summary": "Gets new messages", "nickname": "getUsermessages", "type": "string", "parameters": [ ( "paramType": "path", "name": "sessionToken", "type": "string", "required": true, "allowMultiple": false, "description": "The token from an active user session" ) ], "responseMessages": [ ( "code": 200, "message": "json (messages => "user_messages")" ), ( "code": 400, "message": "json with error "not logged in "" ) ], "notes": "", "authorizations": () ), ( "method": "GET", "summary": "Gets messages paged", "nickname": "getUsermessagesPaged", "type" : "string", "parameters": [ ( "paramType": "path", "name": "sessionToken", "type": "string", "required": true, "description": "The token from an active user session" ), ( "paramType": "query", "name": "numMessages", "type": "string", "required": true, "description": "number of messages on page (numMessages & pageNr are ignored if not both are set)" ), ( "paramType": "query", "name": "pageNr", "type": "string", "required": true, "description": "pagenumber ( numMessages & pageNr are ignored if not both are set)" ) ], "responseMessages": [ ( "code": 200, "message": "json (messages => "user_messages")" ), ( "code": 400 , "message": "json with error "not logged in"" ) ], "notes": "", "authorizations": () ) ] ), ( "path": "/user/userdata", "operations" : [ ( "method": "POST", "summary": "Posts userdata", "nickname": "postUserdata", "type": "string", "parameters": [ ( "paramType": "form", "name": "sessionToken", "type": "string", "required": true, "allowMultiple": false, "description": "The token from an active user session" ), ( "paramType": "form ", "name": "password", "type": "string", "required": false, "allowMultiple": false, "description": "new password" ), ( "paramType": "form", " name": "address", "type": "string", "required": false, "allowMultiple": false, "description": "new address" ), ( "paramType": "form", "name": "housenr", "type": "string", "required": false, "allowMultiple": false, "description": "new housenr" ), ( "paramType": "form", "name": "zip" , "type": "string", "required": false, "allowMultiple": false, "description": "new zip" ), ( "paramType": "form", "name": "city", "type ": "string", "required": false, "allowMultiple": false, "description": "new city" ), ( "paramType": "form", "name": "email", "type": " string", "required": false, "allowMultiple": false, "description": "new email" ) ], "responseMessages": [ ( "code": 200, "message": "json (user => "userdata ")" ), ( "code": 400, "message": "json with error

It seems to be a bug that my swagger-ui is not sending any request parameters? Here is an example with one query-param, sessionToken: (controlled by FireBug 2.0.6)

GET /ias/public/user/balance HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 Accept: application/json Accept-Language: de, en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Content-Type: application/json Referer: http://localhost/ias/swagger/ Cookie: __utma=111872281.581414660.1366700677.1394721873.1394723866.255; uvts=sB5Dda3cZBNdaTk; searchpanel-close=set Connection: keep-alive

The answer was:

HTTP/1.1 400 Bad Request Date: Tue, 25 Nov 2014 14:58:20 GMT Server: Apache/2.4.9 (Win32) PHP/5.5.12 X-Powered-By: PHP/5.5.12 Content-Length: 25 Connection: close Content-Type: application/json; charset=utf-8

The answer was correct because no sessionToken was passed.

This needs work, but it doesn't come from swagger-ui:

GET /ias/public/user/balance?sessionToken=HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0 Accept: text/html,application/ xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: __utma=111872281.581414660 .1366700677.1394721873.1394723866.255; uvts=sB5Dda3cZBNdaTk; searchpanel-close=set Connection: keep-alive

Overview

The built in notification system, first ever in Joomla, allows your app to keep the user (or group of users) informed about various different events. Think of notifications as important alerts that the user would be interested to read and keep track of it.
Notifications can be generated everywhere. In your component or plugins and later displayed inside JomSocial notification system.
This tutorial will show you how, but since third we do not have idea of ​​any-party component we could use:) the examples will be done on a community plugin which will be triggered at onAfterProfileUpdate event
If you don't know how to create plugin which will be triggered on this event, we suggest you to check this guide

Implementing it in your component anyway

As stated in overview of this tutorial, we will generate notifications using community plugin.
You will most likely want to create notifications inside your component, or your plugin. The following tutorial will work in any of these cases. You only need to determine at what point in your code the notification will be created and just load the JomSocial Core Libraries file.

require_once JPATH_ROOT . "/components/com_community/libraries/core.php" ;

Following the tutorial explained bellow will work just fine for your extension too

Preparing the Development Environment

1. We will assume that you "re already created community type example plugin which will be triggered when user changes its profile
If not, you can download empty example plugin from , install it in Joomla and enable the plugin. It is named Community - Notification Example
2. Navigate to your database and empty these two tables, so they dont have any records at all

A) prefix_community_notification
b) prefix_community_mailq

3. Have at least two (2) users at your test sites and know their ID's

In earlier versions of Joomla, user ID"s have always started from specified number (62, 42) In Joomla 3, this number will be random, hence, the picture of our testing environment because it will definitely be different at your end.

The First Notification

Open the plugin php file which will be located in ROOT/plugins/community/example
Within the function onAfterProfileUpdate() replace the

CNotificationLibrary:: add ( $cmd , $actor , $target , $subject , $body , $template , $params ) ;

As shown on the example, notification add api have 7 parameters

  • $cmd - is the notification type. You can see all notification types in this file. ROOT/components/com_community/libraries/notificationtypes.php starting from, or around line 53. We recommend using system_messaging notification type.
  • $actor - is the person who carries out the action
  • $target - is the person, or group of people that will receive notification
  • $subject - is the notification subject, in both, notification popup window and the email title
  • $body - is the body of email notification message
  • $template - if you need specific template to use, you can define it here. Otherwise, this parameter can be empty
  • $params - custom defined parameters
  • Knowing all this, lets define the variables we will use
    Change your plugin code to:

    $user = CFactory::getUser(); $cmd = "system_messaging" ; // first param, type of activity $actor = $user -> id ; //second param - get the id of $actor $target = "965" ; // third param. Who will receive the notification? In our dev environment, its admin user with id 965. At your environment, you will most likely want to get the ID from your object or from array of users. $subject = "Notification Subject" ; // Subject of both, email and popup notifications $body = ; //Body message in emails. $template = "" ; // If you need to use specific jomsocial template file, you can define it here. $params = new CParameter("" ) ; // We want to create an additional params object, and assign data to it, without having to formally define a class CNotificationLibrary:: add ( $cmd , $actor , $target , $subject , $body , $template , $params ) ;

    Now login with any user and change the profile information. Lets go to database to see what happened.
    Navigate to prefix_community_notifications table and observe the new record

    Navigate to prefix_community_mailq table, and see the new record

    Congratulations! - You have successfully created your first very own notification which has been dispatched via email and internal JomSocial notification system


    Potential Code Bloat

    Above example is fine, and it works, but generally it is not recommended to use it like that. Instead, it could be written like this

    $actor = CFactory::getUser(); $params = new CParameter("" ) ; CNotificationLibrary:: add ( "system_messaging" , $actor -> "This is the notification body message" , "" , $params ) ;

    This is much cleaner and easier to follow while basically doing absolutely the same thing as a code shown above.

    Custom Notification Parameters

    A notification API can be extended with any param you would like to add.
    These params can be passed to either email template, notification, and of course, language file.

    $actor = CFactory::getUser(); $link = "http://www.google.com" ; $params = new CParameter("" ) ; $params -> set ("actor" , $actor -> getDisplayName () ) ; // can be used as (actor) tag $params -> set ("actor_url" , "index.php?option=com_community&view=profile&userid=" . $actor -> id ) ; // Link for the (actor) tag $params -> set ("url" , $link ) ; //url of the whole activity. Used when hovering over avatar in notification window. Can be used as (url) tag in outgoing emails too. Make sure that you have defined $link variable:) CNotificationLibrary:: add ( "system_messaging" , $actor -> id , "965" , "Notification Subject" , "This is the notification body message" , "" , $params ) ;

    • $params = new CParameter( ); - We want to create a new params object, and assign data to it, without having to formally define a class.
    • $params->set("actor", $actor->getDisplayName()); - Your notification should always have an actor. This param can be passed to template as (actor) tag. In notification window, it defines the user that carries an action.
    • $params->set("actor_url", "index.php?option=com_community&view=profile&userid=" . $actor->id); - Actor URL is usually the url of an actor. In notification popup, it adds the link to the (actor) element
    • $params->set("url", $link); - This is the most important paramater you must always set properly. In notification window, this param is used over the avatar image. In email notification, it echoes the location where activity occurred.

    For this example, we will set variable $link to lands on www.google.com so you can see how it works

    Adding Language String and Use Params

    Having the params we just set are available to be used in our language files as well.
    Lets define the language keys by altering the " CNotificationLibrary::add() API

    CNotificationLibrary:: add ( "system_messaging" , $actor -> id , "965" , JText:: sprintf ("PLG_COMMUNITY_EXAMPLE_SUBJECT" ) , JText:: sprintf ("PLG_COMMUNITY_EXAMPLE_BODY" ) , "" , $params ) ;

    The language file should look like this

    PLG_COMMUNITY_EXAMPLE_SUBJECT = "(actor) updated profile" PLG_COMMUNITY_EXAMPLE_BODY = "Hi Admin \n This is the mail to inform you that (actor) updated profile \n\n If you want to go to Google, click here \n a href=" _QQ_" (url)" _QQ_">(url)"

    In this example, we have used the tag (actor) and (url) to pass the data to both, notification, and email templates. Lets see how does that look.
    In notification window when hovering over avatar, notice the (url) param kicked in and adds the link to google over avatar. It is intentional, because we made it that way :)


    ]

    In the same window, when hovering over actor link. This is the part where (actor) echoed the user that carries an action, while (actor_url)" taken care that object is linked properly


    Lets see what happens in the email queue


    And finally, the actual email that is sent to end user


    success
    Till now, we created three (3) parameters that are successfully used in notification window, and emails.

  • (actor) - Returns the username of the user which carries the action
  • (actor_url) - Gives the attribute to the (actor)
  • (url) - Is not mandatory, but you should always have it in your notification. It is the main url where action that we are notified about happened.
  • Likewise, you can define "

    • (target) - if you need it
    • (target_url) if you need it in your notification.
    • (title) - Commonly used to refer to an object that generated notification. Example: "User X posted new photo in Album Y ." Album Y is title here
    • (title_url) - As with previous ones, the url of an object that generated notification.
    • (message) - This param can be used to set (and echo) the message in the body of JomSocial email.

    In the end, I realized: there is no one better than a wife. It remains only to find a wife

    PHP AJAX CRUD: create, delete, edit records in MySQL database

    In this article, we will learn about how to add, edit and delete records in a MySQL database using PHP. We've used a jQuery handler that sends an AJAX request to a server script. The handler updates the list of entries.

    AJAX form for sending requests to create, delete, edit

    When a record is added, the form sends the data to the PHP script via an AJAX request. In case of successful addition, the list of entries is reloaded.

    jQuery AJAX functions to query database CRUD

    In the jQuery AJAX function, we have a toggle for add edit and remove cases. These cases generate different query strings and response data depending on the actions of the database.

    function showEditBox(id) ( $("#frmAdd").hide(); var currentMessage = $("#message_" + id + " .message-content").html(); var editMarkUp = ""+currentMessage+" SaveCancel"; $("#message_" + id + " .message-content").html(editMarkUp); ) function cancelEdit(message,id) ( $("#message_" + id + " .message-content") .html(message); $("#frmAdd").show(); ) function callCrudAction(action,id) ( $("#loaderIcon").show(); var queryString; switch(action) ( case "add ": queryString = "action="+action+"&txtmessage="+ $("#txtmessage").val(); break; case "edit": queryString = "action="+action+"&message_id="+ id + " &txtmessage="+ $("#txtmessage_"+id).val(); break; case "delete": queryString = "action="+action+"&message_id="+ id; break; ) jQuery.ajax(( url: "crud_action.php", data:queryString, type: "POST", success:function(data)( switch(action) ( case "add": $("#comment-list-box").append(data); break; case "edit": $("#message_" + id + " .message-content").html(data); $("#frmAdd").show(); break; case "delete": $("#message_"+id).fadeOut(); break; ) $("#txtmessage").val(""); $("#loaderIcon").hide(); ), error:function ()() )); )

    PHP script for CRUD operations

    The following code executes database queries. This PHP script, after performing a CRUD action, updates the records as a result of the AJAX response.

    require_once("dbcontroller.php"); $db_handle = new DBController(); $action = $_POST["action"]; if(!empty($action)) ( switch($action) ( case "add": $result = mysql_query("INSERT INTO comment(message) VALUES("".$_POST["txtmessage"]."")" ); if($result)($insert_id = mysql_insert_id(); echo " Edit Delete " . $_POST["txtmessage"] . " "; ) break; case "edit": $result = mysql_query("UPDATE comment set message = "".$_POST["txtmessage"]."" WHERE id=".$_POST["message_id"]); if($result) echo $_POST["txtmessage"]; break; case "delete": if (!empty($_POST["message_id"])) ( mysql_query("DELETE FROM comment WHERE id=".$_POST["message_id"]); ) break; ) )

    3.3K

    Displaying messages to the user is a fairly common action that a web application should perform. It can happen while processing forms, it can be error messages, messages that say you need to register when a user tries to access a restricted part of the site, and in many other cases.

    Very often, the creation and output of messages are separated by different HTTP requests. As a rule, it is convenient to use a redirect after forms have been processed (to avoid problems with the Back and Refresh buttons), but at the same time, the natural moment for creating a message is precisely the moment of processing the forms and performing the actions that accompany it. Why? Imagine that the text of the message should look something like this: "The number of ordered units of the item 'Mouse Pad' has been successfully changed from 7 to 12." After a redirect, perhaps to a page that is completely different in terms of functionality, it will be an extra head - to determine what was done before.

    Most often, messages are displayed in the POST request that processes the form - this is not good, the inscriptions "this page is out of date" spoil life (when the user wants to try the Back button).

    Someone uses a redirect, giving up on friendly messages.

    At the same time, there is a simple and obvious way to make life better. Despite the obviousness, for some reason I never saw anyone use it - at least when I looked at other people's sources.

    So, we have a problem - the message should "live" in different requests. We need a mechanism to pass the text of the message to the page that should display it. You probably already remembered the sessions.

    Yes, in general you are right. Other methods, for example, through a global variable, do not allow saving data in the case when a redirect is used (remark by Maxim Naumenko). Plus, I usually make sure that each screen in the application has the ability, along with other information, to display messages that were generated on previous screens. This is convenient because there is no need to prepare separate screens for displaying messages, and the user does not have to click the mouse again. But, really, here the designer needs to think - to highlight the area in which the messages would appear.

    The idea is very simple and can be implemented with a couple of classes.

    The first thing that comes to mind is to create a Message class, which, in fact, would represent a message on our simple class diagram. The message must be able to save itself in the session, as well as display itself on the screen.

    class Message ( /** * Message content. */ var $content; /** * Constructor to initialize message text. * * @param content message content */ function Message($content) ( $this->content = $content ; ) /** * Write the message to the session */ function send() ( $_SESSION["session_messages"] = $this->content; ) /** * Send the message to the page */ function toPage() ( echo "-" . $this->content . "
    "; } }

    The $_SESSION variable is used to access the session.

    Note that $_SESSION is an array, we only use one element of this array with index 'session_message'.

    In this case, we are dealing with an "array of arrays" - what we store in the 'session_message' element is an array, this is the list of transmitted messages (there may be several of them, of course).

    If you couldn't find the thread, it's time to brush up on the sections of the manual on sessions and arrays.

    You may have a question. Why are classes needed here? It would be possible to get by with two functions. But let's look further. We may need to create messages with different types (info, error, warning), define message recipients.

    Note that at the moment, not the object itself is put into the session, but only the text of the message. OOP allows us to change the behavior of the send() method in the future without changing the client code that calls this method (for example, in the future, the entire Message object can be written to the session if it has many fields).

    Let's imagine that we would do it with the help of functions. Probably, we would have a message_send($txt) function, we would also have a message_to_page($txt) function. Now we need to add the possibility of different behavior for different types of messages. Function calls change: message_send($txt, $kind), message_to_page($txt, $kind). You will have to comb through the entire application code in search of such functions, making corrections.

    This can be avoided by anticipating the situation in advance by presenting the message as an associative array: $msg['txt'], $msg['kind'], then there will be only one parameter in function calls. Do you feel how it tends to turn into a class?

    Well, OOP gives you the luxury of not having to think things through in advance.

    The next class - Inbox - is just for this purpose.

    class Inbox ( /** * Array of incoming messages. */ var $messages = array(); /** * In the constructor, get all incoming messages * and remove them from the session. */ function Inbox() ( if (is_array($ _SESSION["session_messages"])) ( $messages = $_SESSION["session_messages"]; $co = sizeof($messages); for ($i = 0; $i< $co; $i++) { $this->messages = new Message($messages[$i]); ) ) /* clear the array of messages */ $_SESSION["session_messages"] = array(); ) /** * Display the contents of the Inbox on the page. */ function toPage() ( $co = sizeof($this->messages); if ($co > 0) ( echo "Message from system:
    "; ) for ($i = 0; $i< $co; $i++) { $this->messages[$i]->ToPage(); ) ) )

    Let's test our messaging system.

    Let's create a very simple example that, in response to a form submission, will report the number of seconds in the current minute.

    We have hidden all the work with arrays and sessions inside classes, and the final code looks simple and beautiful.

    Create a directory on the web server, then create these three files in it and try the script out. Note that there are no problems with the Back and Refresh buttons.

    Now imagine that you are creating a complex portal, where, as a rule, there are several blocks on the pages, and each can contain a separate application inside.

    Here we encounter two difficulties:

    * I would like the list of messages to appear in a certain part of the page, and you have already found a good place for this.
    The problem is that you need to run the $inbox->toPage() command exactly at the moment that would correspond to the position of the list of messages on the page. If we want to change the position of this list, we will have to get into the code, but it is not good to constantly change the portal framework for this. The best solution would be to make the output of messages in the form of a separate module, which is known only to be connected to the framework.
    That is, to get rid of the strict sequence of launching modules. Indeed, since the result of the Inbox output does not depend on the operation of the system (at this step, we already have all the data in the session), then why the extra complexity?
    * To maintain the appearance (design) of the message list, you need to take care of the HTML code that we have wired up in the toPage () methods of the Message and Inbox classes. As a rule, you will have to change the PHP code in order to change the design.

    To try to solve the first problem, you can create a buffer that would store the result of the output of the Inbox.

    Perhaps we will still have a few similar (to Inbox) things, and we need to create a system of buffers. In order not to confuse where whose output is, we will probably come to the naming of buffers. We will have somewhere stored the sequence in accordance with which the output of buffers should occur - preferably in an external file, so that it is easier to make changes.

    Already this attempt at a solution gives us the idea of ​​using XML as a means of storing intermediate data. And the use of XSLT styles will help to cope with the second problem.

    I won't dwell on what is XML and what is XSLT. If you are unfamiliar with these things, zvon.org is a good starting point for learning.

    The idea is to form not HTML code, but XML structure in the toPage() methods. The page document will be created as a string with XML code (it will serve as a "buffer"), and in the last stage of the script, we will use the XSL transformation.

    To begin with, imagine what should be the result of the work of the main part of the code.

    minute 57 second: 45

    What it is - it's quite easy to guess - two messages and a form. Note that the PHP script only needs to prepare this string - it's very simple. Moreover, the order of the main tags is unimportant - you can put it first, for example, as it will be convenient for the programmer. How to implement it. It is possible, almost without changing anything, to use output buffering, output XML instead of HTML code, and at the end simply capture the output to a string. But then we will lose in flexibility - for example, sometimes you want to display debugging information directly on the page (using echo). At the same time, the PHP developers are working on a DOM module that offers a more advanced way of creating and passing tree-like documents. If we want to inject the DOM, we will have to redesign the entire application, changing the output of strings to create DOM elements. Therefore, I prefer to store the XML representation of the objects within the objects themselves, building up the overall XML document in sequence. It's not that hard, just a little modification is needed. You will see that this technique is not strictly tied to a particular way of storing XML data, and this will allow you to make the transition to using the DOM "with little bloodshed". First of all, note that each of our objects has a toPage() method. This similarity should make us think about introducing a new common parent class. Let each class that is able to create pieces of the XML document for the page inherit from a class that will take care of the XML representation of the object. Let's call it Outputable.

    class Outputable ( /** * XML container (string). */ var $output = ""; /** * Give the contents of the container and clear the container. * * @return string with XML data */ function getOutput() ( $ out = $this->output; $this->output = ""; return $out; ) /** * Append a portion to the contents of the container. * * @param string the string to append */ function appendOutput($string) ( $this ->output .= $string ."n"; ) /** * "Abstract" method.*/ function toPage() ( ) )

    The toPage() method is made empty - in this case, it is needed as an indicator of how the outer "matryoshka" classes should communicate with the inner class. However, a default implementation could be suggested here if we noticed that there are many objects that display themselves in the same way on the page.

    The Message and Inbox classes will change a little - now both of them should inherit from Outputable, and the toPage () methods will also change
    message.php

    class Message extends Outputable ( /** * Message content. */ var $content; /** * Constructor to initialize message text. * * @param content message content */ function Message($content) ( $this->content = $content; ) /** * Write the message to the session */ function send() ( $_SESSION["session_messages"] = $this->content; ) /** * Send the message to the page */ function toPage() ( $this->appendOutput("".$this->content.""); ) )

    class Inbox extends Outputable ( /** * Array of incoming messages. */ var $messages = array(); /** * In the constructor, get all incoming messages * and remove them from the session. */ function Inbox() ( if (is_array ($_SESSION["session_messages"])) ( $messages = $_SESSION["session_messages"]; $co = sizeof($messages); for ($i = 0; $i< $co; $i++) { $this->messages = new Message($messages[$i]); ) ) /* clear the array of messages */ $_SESSION["session_messages"] = array(); ) /** * Display the contents of the Inbox on the page. */ function toPage() ( $co = sizeof($this->messages); $this->appendOutput(""); for ($i = 0; $i< $co; $i++) { $this->messages[$i]->toPage(); $this->appendOutput($this->messages[$i]->getOutput()); ) $this->appendOutput(""); ) )

    The output method has changed - now instead of directly outputting to the page, the external representation is stored for the time being in the Outputable, which "sits" in each of the objects. The appendOutput() method serves as a kind of replacement for the echo() construct. To get the output of an object, the getOutput() method is used.

    Now let's see what the client part of the code is, which will solve the same task as before.
    index.php

    The main innovation is in the $global_content object, whose name speaks for itself. In this case it belongs to the Outputable class, in real life you would probably create a separate class for the content of the page.

    If you look closely, the content of the script has not changed much - the same inbox, the same toPage(). Added an instruction that outputs the contents of the message list to the page content. For a change, two messages are now generated.

    In order to look at the result, it remains only to prepare the XSL template.
    style.xsl

    XSLT Example

    message

    What have we achieved?

    First of all, you can take on complex projects more boldly - the real independence of the modules is ensured. The order of stacking results on the page is now controlled by an external XSL template and does not depend on the order in which modules are launched.

    Any module that generates XML data as a result of its work can be used in a project. By the way, this is one of the advantages over template engines, in which data creation consists in the sequence of calling methods (assign, etc.) of a particular engine, which do not have a common standard.

    Another benefit is ease of debugging. If you run the script, you'll notice that each page has debug output, an XML prototype that makes debugging applications a lot easier.

    Another thing to think about is how to create message objects. It's not always convenient to use new directly in client code. But, perhaps, this is a topic for a separate article.

    Finally, a gallop about the prospects:

    * pop-up windows for a list of important messages
    * "Sender pages" and "Destination pages" in messages
    * logging messages in the database
    * button "show the history of my actions"
    * statistical analysis of user actions within sessions
    * "intelligent assistants" in web applications