ITX Rock my Web App

April 28th, 2008

When working on web applications, it is obvious to separate the design of a website from its core logic. Not only can different people edit the bits, it also ensures a certain design consistency is created. There are many ways to use template but one of the most prominent is PEAR’s IT/ITX. But even those have a huge potential for reuse that is not obvious.

A Subtle Introduction

If you check out the PEAR module HTML_Template_IT you will see that using it is straight forward.

Let’s write a friendly greeting program. It will get a title and message via GET or POST and display it. The simple implementation is something like:

<?php
    if (isset($_REQUEST["title"]))
    {
        $title = $_REQUEST["title"];
    }
    else
    {
        $title = "Greeting";
    }
    if (isset($_REQUEST["message"]))
    {
        $title = $_REQUEST["message"];
    }
    else
    {
        $title = "No message specified.";
    }
?>
<html>
    <head>
        <title><?php echo $title ?></title>
    </head>
    <body>
        <div align="center">
            <?php echo $message ?>
        </div>
    </body>
</html>

Now the problem is that the HTML is entangled with the code. If you have a similar page with totally different logic you end up duplicating your design. If you ever have to change something you have to do it everywhere, not to mention site wide design changes.

We will now rewrite the program to use IT template. For this we will first write the template.

<html>
    <head>
        <title>{title}</title>
    </head>
    <body>
        <div align="center">
            {message}
        </div>
    </body>
</html>

This is quite simple the {title} and {message} are place holders that are substituted. To do this we change the application as follows.

<?php

require_once "HTML/Template/IT.php";

if (isset($_REQUEST["title"]))
{
    $title = $_REQUEST["title"];
}
else
{
    $title = "Greeting";
}
if (isset($_REQUEST["message"]))
{
    $title = $_REQUEST["message"];
}
else
{
    $title = "No message specified.";
}

$template = new HTML_Template_IT("./tpl");

$template->loadTemplateFile("message.tpl", true, true);

$template->setVariable("title", $title);
$template->setVariable("message", $message);

$template->show();

The code is quite self explanatory. You create a HTML_Template_IT object and then load the template with loadTemplateFile. The variable substitution is done with setVariable and the compiled template is printed with show.

Now we can consistently show different messages from different applications. The problem now comes when you consider site wide design changes. In this case you have to go to the next level and use ITX.

The Next Level

Now let’s consider you have a finished design and you convert it to a template.

<?xml version="1.0" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html>
    <head>
        <title>{title} - MySite</title>
        <meta name="author" content="{author}">
        <meta name="description" content="{description}">
        <meta name="keywords" content="{keywords}">
        <link rel="stylesheet" type="text/css" href="{url}/tpl/style.css" />
    </head>
    <body>
        <div class="page">
            <div class="header"></div>
            <div class="main">
                {main}
            </div>
            <div class="footer">
                &copy; 2008 Jon Doe |
                <a href="{url}/contact.php">Contact</a>
            </div>
        </div>
    </body>
</html>

This the basic outline every page gets and is the basic design of the site. Please note that placeholders for menus and such where omitted in the example.

This design is nice, only how do I get the different content there. Well there is the simple solution, put it all into main place holder. Since we want to reuse it we encapsulate all the template handling into a Page object.

The Page object is fairly simple:

<?php
require_once 'HTML/Template/ITX.php';
require_once 'inc/config.php';

class Page
{
    var $template;

    function Page($title)
    {
        $this->template = new HTML_Template_ITX(get_template_path());
        $this->template->loadTemplatefile('main.tpl', true, true);

        $this->template->setVariable('url', get_config('site', 'url'));
        $this->template->setVariable('title', $title);

        $this->template->setVariable('author', get_config('site', 'author'));
        $this->template->setVariable('description', get_config('site', 'description'));
        $this->template->setVariable('keywords', get_config('site', 'keywords'));
    }

    function set_main($value)
    {
        $this->template->setVariable('main', $value);
    }

    function show()
    {
        $this->template->show();
    }
}

The Page class basically loads the template and sets the common values. These values are pulled via get_config but you can do it in any way you like.

The class is used as follows:

<?php
require_once "inc/Page.php";

if (isset($_REQUEST["title"]))
{
    $title = $_REQUEST["title"];
}
else
{
    $title = "Greeting";
}
if (isset($_REQUEST["message"]))
{
    $title = $_REQUEST["message"];
}
else
{
    $title = "No message specified.";
}

$page = new Page($title);
$page->set_main("<div align=\"center\">{$message}</div>");
$page->show();

This is quite ok. But you can see the issue coming, you need to assemble tons of HTML bits to make a large page.

Explicit Message Page

Since we want the most explicit solution, we will create a Message_Page. To do this we start with a template.

<!-- BEGIN message -->
<div align="center">{message}</div>
<!-- END message -->

Well this is the missing bit. Its not much, but messages look this way.

The Message_Page is a s follows:

<?php

#include "Page.php"

class Message_Page extends Page
{
    function Message_Page($title)
    {
        $this->Page($title);

        $this->template->addBlockFile('main', 'main', 'message.tpl');
        $this->template->setCurrentBlock('message');
    }

    function set_message($text)
    {
        $this->template->setVariable('message',   $message);
    }

    function show()
    {
        $this->template->parseCurrentBlock('message');
        Page::show();
    }
}

Well this is where it gets interesting, we insert one template into an other by calling addBlockFile. The template message.tpl is inserted into the main placeholder and converted to a block. We add a setCurrentBlock, parseCurrentBlock pair, so that the variable scoping works properly.

Easy Forms

This seems slightly overkill, but consider the following example.

You want also to have forms on your page. The simple way is to build one template with the entire form and substitute that. But there is a nifty solution, built the form from template bits.

Here is the template:

<!-- BEGIN form -->
<h1>{title}</h1>
<!-- BEGIN instructions -->
<p>{instructions}</p>
<!-- END instructions -->
<form method="{method}" action="{action}">
    <table>
        <!-- BEGIN input -->
        <tr>
            <td valign="top">{name}</td>
            <td><input type="text" name="{variable}" value="{value}" size="{size}" /></td>
        </tr>
        <!-- END input -->
        <!-- BEGIN text -->
        <tr>
            <td valign="top">{name}</td>
            <td><textarea name="{variable}" cols="{cols}" rows="{rows}">{value}</textarea></td>
        </tr>
        <!-- END text -->
    </table>
    <input type="submit" value="{submit}">
</form>
<!-- END form -->

How this template works, we will see with the Form_Page class:

<?php

require_once 'Page.php';

class Form_Page extends Page
{
    function Form_Page($title, $method, $action)
    {
        $this->Page($title);

        $this->template->addBlockFile('main', 'main', 'form.tpl');

        $this->template->setCurrentBlock('form');
        $this->template->setVariable('title',    $title);
        $this->template->setVariable('method',   $method);
        $this->template->setVariable('action',   $action);
    }

    function set_instructions($text)
    {
        $this->template->setVariable('instructions', $text);
    }    

    function add_input($name, $variable, $value = '', $size = 50)
    {
        $this->template->setCurrentBlock('input');    

        $this->template->setVariable('name',     $name);
        $this->template->setVariable('variable', $variable);
        $this->template->setVariable('value',    $value);
        $this->template->setVariable('size',     $size);

        $this->template->parseCurrentBlock('input');
    }

    function add_text($name, $variable, $value = '', $cols = 50, $rows = 10)
    {
        $this->template->setCurrentBlock('text');    

        $this->template->setVariable('name',     $name);
        $this->template->setVariable('variable', $variable);
        $this->template->setVariable('value',    $value);
        $this->template->setVariable('cols',     $cols);
        $this->template->setVariable('rows',     $rows);

        $this->template->parseCurrentBlock('text');
    }

    function set_submit_text($text)
    {
        $this->template->setVariable('submit', $text);
    }

    function show()
    {
        $this->template->parseCurrentBlock('form');
        Page::show();
    }
}

Well basically it is the same as with Message_Page, the template is substituted into the main placeholder and common values are used. The difference comes with add_text and add_input.

Since blocks can be reused, multiple calls to add_input, will add multiple fields. The following application shows the Form_Page in action by using a contact form.

<?php
require_once 'inc/Form_Page.php';

$page = new Form_Page('Contact', 'POST', 'contact.php');

$instructions = 'If you whish to contact us, please us the following form.' .
                'We will reply via e-mail in the comming days.';
$page->set_instructions($instructions);

$page->add_input('Name', 'name');
$page->add_input('E-Mail', 'email');
$page->add_text('Text', 'text');
$page->set_submit_text('Send');

$page->show();

Static Content

Every web application has static content, to simplify access to this, I created a Static_Page class. This page will load the content from a text file and add it verbatim into to main placeholder.

<?php

require_once 'Page.php';
require_once 'inc/config.php';

class Text_Page extends Page
{
    function Text_Page($title, $text_file)
    {
        $this->Page($title);    

        $text = $this->read_text($text_file);
        $this->template->setVariable('main', $text);
    }

    function read_text($text_file)
    {
        $content_file = get_data_path() . $text_file;
        $fh = fopen($content_file, "r") or die("Could not open $content_file.");
        $content = fread($fh, filesize($content_file));
        fclose($fh);
        return $content;
    }
}

A static page would use it as follows:

<?php 

require_once 'inc/Static_Page.php';

$template = new Static_Page('Example', 'example.txt');
$template->show();

PHP and MySQL

ecx.images-amazon.com_images_i_51rlqgd8q5l._sl160_.jpg

PHP and MySQL

Well I must addmit that I did not come to the idea fully on my own. The concept with recycling templates and building forms from blocks in templates was taken from the very good book PHP and MySQL from O’Reilly.

But I cleaned up the concept and code, since I think the author is a crappy programmer, although the concepts are nice. To state a example he reuses the templates by inheriting from the HTML_Template_ITX class. Well sorry, inheritance is not for code reuse and a page definitely is not a template.

Links


Big Changes, Step by Step

April 21st, 2008

Working with legacy code can be frustrating and often you might want to scrap everything and rewrite it. Many projects try this and in almost all cases they fail at it. They have a really hard time, because the problem at hand was not as simple as it seemed.

What people ignore is the fact that the code contains a large number of little bits of knowledge, quicks of the system that are not obvious. This knowledge was gained though long years of maintenance and the inherent problem is that this knowledge gets lost on a rewrite.

On the other hand, legacy code can become a maintenance nightmare. Something has to be done to improve code quality, rejuvenate the code and thus reduce the maintenance burden.

The solution is to make many small changes and improve the code quality day by day. By refactoring the existing code the knowledge within the code is not lost and you have a running system all the time.

The Beauty of C++ Cast Operators

April 19th, 2008

Many criticize the C++ explicit cast operators. Common points of critique is that they are clumsy or redundant. But I believe that most people who are criticizing the cast operators did not understand what the point is about them.

A Bit of Theory

If you do not know what I am talking about, the explicit cast operators are static_cast, reinterpret_cast, dynamic_cast and const_cast. Every cast operator has its own use, lets see what it is.

The const_cast operator is there to add or remove const or volatile. It is not often used, but some cases where you are working with “broken” third party libraries, this operator can be required.

The dynamic_cast is used then casting polymorphic objects. It is a safe cast since it only returns a useful result when the cast is successful. This is done with the help of runtime type checking and can give a slight performance hit.

The reinterpret_cast is used when you blindly want to map the bit pattern from one type into the other. This was never possible with C casts.

The static_cast is the simplest cast there is. It is almost the analogue to the C cast, except for removing or adding const or volatile. It can do the same things as dynamic_cast only the safety disabled.

Casts are Evil

Although this bold statement is slightly exaggerated, if you have casts in your code there is a good chance that there is a flaw in your design. Casts mean that you convert from one type into the other, why is the data not the the format you need it?

It is true that you need casts when you connect two pieces of software together, such as adding some third party software to yours. But even here the requirement to convert from one format to the other is a flaw, even though it might be only a minor flaw.

Every time you cast data can be lost or potentially turn out to nonsense. The new cast operators make the cast clearly visible and debugging often becomes easier, since potential places of data loss are clearly marked.

Not Really Awkward

The cast operator look like functions and if you really think about it they are not as awkward as C casts. In addition concepts such as lexical_cast or any_cast where easily accepted the syntax closely follows the “real” C++ casts.

If you ever accessed a member with a C cast, compare the two alternatives:

// C cast
((MyType*)value)->some_member;

// C++ cast
dynamic_cast<MyType*>(value)->some_member;

Not that this code is good style, since the cast may fail. But the C++ cast does not need any odd parentheses and you can’t cast the result by mistake.