Messages in the web-applications

Message outputting is a widely spread activity that should be executed by the web-application. During form processing, for example, there can appear such messages as error messages, or messages that tell user that he need to register while accessing the restricted part of the site.

Messages are created and output in different HTTP-queries. As a rule there is used redirect after form processing for escaping problems with Back and Refresh buttons.

As a rule messages are output in the POST query that process the form. Message should ‘live’ in different queries. We need the mechanism that can pass the message text to the page that will output it.

The idea is very simple; it can be implemented using several classes. At first we’ll create Message class. Message has to be abele to save itself to the session and print to the screen.

Message.php

 <?php class Message
{

/**
* Content.
*/
var $content;

/**
* Constructor for message text initializing
*
* @param content message content
*/
function Message($content)
{
$this->content = $content;
}

/**
* writing to the session.
*/
function send()
{
$_SESSION[“session_messages”][] = $this->content;
}

/**
* Printing to the page.
*/
function toPage()
{
echo ” – ” . $this->content . “<br>”;
}

} >?

$_SESSION variable is used for accessing the session. $_SESSION is an array; we use only one element of that array with ‘session_message’ index.

You can say that we don’t need classes, and two functions would be enough. But there can appear necessity of creating different messages (info, error, warning).

Notice that in that moment object isn’t put to the session, only message text. OOP allows to change the send() method’s behavior without changing the client code, which calls that method.

Let’s suppose that we used functions. Probably we would have message_send($txt) and message_to_page($txt) functions. Now we have to add the opportunity of changing behavior of different types of the messages. Functions calls changes: message_send($txt, $kind), message_to_page($txt, $kind). We’ll have to look through the whole code searching these functions.

We can escape such situation if represent the message as a associative array $msg[‘txt’], $msg[‘kind’].

All inbox messages should be printed in every page, and deleted from the session after that. Next class is Inbox class.

Inbox.php

<?php class Inbox
{

/**
* Inbox messages array.
*/
var $messages = array();

/**
* Receive inbox messages in the constructor and delete
* 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 message array */
$_SESSION[“session_messages”] = array();
}

/**
* Print to the page Inbox content.
*/
function toPage()
{
$co = sizeof($this->messages);
if ($co > 0)
{
echo “System message: <br>”;
}
for ($i = 0; $i < $co; $i++)
{
$this->messages[$i]->ToPage();
}
}

} ?>

Let’s test our message system. Let’s create simple example that will show seconds in the minute as an answer to the form sending.

index.php

<?php

include(“Inbox.php”);
include(“Message.php”);

session_start();

if (“POST” == $_SERVER[“REQUEST_METHOD”])
{
$msg = new Message(“msg: ” . date(“s”));
$msg->send();

header(“location:”);
}
else
{
$inbox = new Inbox();
$inbox->toPage();
}

?>
<form method=post action=index.php><input type=submit></form>

That’s it. Working with arrays and sessions we’ve hidden inside the classes.

Create the catalog on the web server and create there these three files. Notice that there are no problems with Back and Refresh buttons.

Now imagine that you are creating a complicated portal where every page has several blocks and every block contains an application. Here we face with the following difficulties:

  • Message list should appear in the definite part of the page. But the problem is that we have to run the $inbox->toPage() command at the moment that corresponds the location of the message list. If we want to change the location of the list we have to change code. But it isn’t good. The best solution is to create the message output as a single module.
  • If you want to support the design of the message list you have to think about the HTML code that is put into the toPage() methods of the Message and Inbox classes. You’ll have to change the php code for changing the design.

To solve that problem we can create the buffer where the result of Inbox output will be stored.

Probably we’ll have several similar things, that’s why we have to create the system of buffers. Consecution will be stored in the external file. According to that consecution buffer output will be carried out.

We’ll use the XML as a method of storing the temporary data. Using XSLT styles will help us to solve the second problem.

The idea is to form XML structure instead of the HTML code in the toPage() methods. Page document will be created as a string with the XML code. At the finishing stage we’ll use the XSL transformation.

At first let’s imagine the result of the main part of the code working.

 <?php <messages>
<message>minute 57</message>
<message>second: 45</message>
</messages>

<refresh_form/> ?>

In that code we see two messages and one form. Notice that PHP should prepare only such string. The order of the tags isn’t important, for example, <refresh_form/> can be put at the beginning. How can we implement it? We can use output buffering and output the XML instead of the HTML code. But in that case we’ll loose the flexibility, for example sometimes we want to output the debug information to the page (using echo). At the same time PHP developers are working on the DOM module that provides modern method of creating and passing the tree type documents. If we want to use DOM we’ll have to change our application. That’s why I prefer using XML. All our objects have toPage() method. That’s why we have to think about creating general parent class. Let’s every class that can create pieces of the XML document for the page will be inherited from the class that will care about object XML representation. Name it Outputable.

 <?php class Outputable
{
/**
* XML container (string).
*/
var $output = "";

/**
* Clear the cntainer.
*
* @return strin with the XML data
*/
function getOutput()
{
$out = $this->output;
$this->output = “”;
return $out;
}

/**
*
*
* @param string added string
*/
function appendOutput($string)
{
$this->output .= $string . “\n”;
}

/**
* “Abstract” method.
*/
function toPage()
{
}
} ?>

Message and Inbox classes will be changed. Now they should be inherited from the Outputable. toPage() methods will be changed too.

Message.php

<?php class Message extends Outputable
{

/**
* Message content.
*/
var $content;

/**
* Constructor for message text initializing.
*
* @param content message content
*/
function Message($content)
{
$this->content = $content;
}

/**
* writing to the session.
*/
function send()
{
$_SESSION[“session_messages”][] = $this->content;
}

/**
* Printing to the page.
*/
function toPage()
{
$this->appendOutput(“<message>”.$this->content.”</message>”);
}

} ?>

Inbox.php

<?php class Inbox extends Outputable
{

/**
* Inbox messages array.
*/
var $messages = array();

/**
* Receive inbox messages in the constructor and delete
* 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 */
$_SESSION[“session_messages”] = array();
}

/**
* Print to the page Inbox content.
*/
function toPage()
{
$co = sizeof($this->messages);
$this->appendOutput(“<messages>”);
for ($i = 0; $i < $co; $i++)
{
$this->messages[$i]->toPage();
$this->appendOutput($this->messages[$i]->getOutput());
}
$this->appendOutput(“</messages>”);
}

} ?>

Now let’s view the client code.

index.php

<?php

include(“Outputable.php”);
include(“Inbox.php”);
include(“Message.php”);

session_start();
$global_content = new Outputable;

if (“POST” == $_SERVER[“REQUEST_METHOD”])
{
/* current minute */
$msg_min = new Message(“minute ” . date(“i”));
$msg_min->send();

/* current second */
$msg_sec = new Message(“second: ” . date(“s”));
$msg_sec->send();

/* redirecting to itself */
header(“location:”);
exit;
}
else
{

/* prepare the message list as an XML */
$inbox = new Inbox();
$inbox->toPage();
$global_content->appendOutput($inbox->getOutput());
}

$global_content->appendOutput(“<refresh_form/>”);

$xml_string = $global_content->getOutput();

$xh = xslt_create();
$xarg = array();

/* XML document header */
$xarg[“xml”] = “<?xml version=”1.0″ encoding=”KOI8-R”?>”.”\n”;

/* XML document body */
$xarg[“xml”] .= “<page>” . $xml_string . “</page>”;

/* XSL-template */
$xarg[“xsl”] = implode(“”, file(“style.xsl”));

/* output HTML-code ‘ result of the XSL-transformation */
echo xslt_process($xh, “arg:xml”, “arg:xsl”, NULL, $xarg);

echo “<hr><pre>” . htmlspecialchars($xml_string) . “</pre>”;
?>

The main innovation is $global_content. In our case it belongs to the Outputable class. The main part of the code hasn’t changed, it has the same inbox, and toPage(). Now here are generated two messages.

To see the result we have to prepare the XSL template.

style.xsl

<?xml version="1.0" encoding="KOI8-R"?>
<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" >

<!’main template that corresponds to the root element–>
<xsl:template match = “/page” >
<html>
<head>
<title>XSLT Example</title>
</head>
<body bgcolor=”#eeeeee”>

<!’output the message list –>
<xsl:apply-templates select=”/page/messages” />

<!’output the form –>
<xsl:apply-templates select=”/page/refresh_form” />

</body>
</html>
</xsl:template>

<xsl:template match=”/page/messages/message”>
<table border=”1″ cellspacing=”0″ cellpadding=”0″>
<tr><th>message</th></tr>
<tr><td class=”message”><xsl:value-of select=”.”/></td></tr>
</table>
</xsl:template>

<!’template output the form with button–>
<xsl:template match=”/page/refresh_form”>
<form method=”POST” action=”index.php”>
<input type=”submit”/>
</form>
</xsl:template>

</xsl:stylesheet>

 

So, what have we reached?

At first, you can start any complicated project, because modules’ independence is guaranteed.

Any module that generates the XML data as a result of its working can be used in the project.

Another advantage is debugging simplicity. If you run the script you could see that every page has the debug-output that lightens the debugging process.

Messages in PHP web-applications

Leave a Reply