The PHP Template

Here is the source code for a class that you can use to construct dynamic web-site pages from skeletal template files, Template.php. What it does seems so obvious that I cannot justify even commenting it:

<?php
class Template
{
    private $file;
    private $vars;
 
    function __construct($file) { 
        $this->file = $file;
    }
 
    public function set($name, $value) {
        if (is_object($value)) {
            $this->vars[$name] = $value->fill();
        } else {
            $this->vars[$name] = $value;
        }
    }
 
    public function fill() {
        extract($this->vars);
        ob_start();
        include($this->file);
        $contents = ob_get_contents(); 
        ob_end_clean();
        return $contents;
    }
}
?>

Refer to the PHP Manual Online for a description of the functions used. The non-obvious ones are those starting with ob_, but these are just related to output buffering.

Here is an example of a template file for use with the above class, page.tpl.php:

<html>
  <head>
    <title>
        <?php echo $title; ?>
    </title>
  </head>
 
  <body>
    <h1>
        <?php echo $title; ?>
    </h1>
 
    <!--
        Fill in a 2-column table from an associative array.
        The first column will contain the array key,
        the second the associated value.
        The Template class must set $array.
    -->
    <table border="1">
      <?php foreach ($array as $key => $value) { ?>
        <tr>
          <td>
            <?php echo $key; ?>
          </td>
          <td>
            <?php echo $value; ?>
          </td>
        </tr>
      <?php } ?>
    </table>
 
  </body>
</html>

Here is a dynamic page that uses the template file and the Template class:

<?php
require_once('./Template.php');
 
$page = new Template('page.tpl.php');
$page->set('title', 'A Simple Template Example');
 
$a = array('Apple' => 'red',
           'Orange' => 'orange',
           'Banana' => 'yellow');
 
$page->set('array', $a);
 
echo $page->fill();
?>

That is really all there is to it! The simple example above probably even covers the majority of the data structures you work with day-to-day: simple variable substitutions and repeated blocks. If you copy and paste the code above into three appropriately named files you will get a page with a simple heading, "A simple Template Example" that shows a three-rowed table listing the colors of the various fruits.

If you look carefully at the Template class you will notice that the set() method accepts either a plain variable or another Template object. If given another Template it will use that object's fill() method to fill in the named template place-holder variable from the (filled-in) Template. For example, suppose the main page template in page.tpl.php was just this:

<html>
  <head>
    <title>
        <?php echo $title; ?>
    </title>
  </head>
 
  <body>
    <h1>
      <?php echo $title; ?>
    </h1>
 
    <?php echo $content; ?>
 
  </body>
</html>

Furthermore, suppose you have a separate table.tpl.php template file that looks like this:

<!--
    The Template class needs to set the $grid variable.
    Everything else is for the presentation logic.
    This assumes that $grid is an arbitrary array of arrays.
    The logic here constructs a table with the proper number
    of rows and columns to fit the entire $grid.
-->
<table border="1">
<?php
    foreach ($grid as $arr) {
        echo "<tr>";
        foreach ($arr as $a) {
            echo "<td> $a </td>";
        }
        echo "</tr>";
    }
?>
</table>

You can fill this table from a database query (or a simple array of arrays) and insert the results into the page template as follows:

<?php
// Phony data -- more likely the results of a database query
$t = array(
      array('John Doe', '1975-12-19', '201 555 1212'),
      array('Jane Doe', '1978-01-01', '201 555 1212')
      // ...etc...
    );
 
require_once('./Template.php');
 
$page = new Template('page.tpl.php');
$page->set('title', 'A Simple Template Example');
 
$table = &new Template('table.tpl.php');
$table->set('grid', $t);
 
$page->set('content', $table);
 
echo $page->fill();
?>

The above examples are simple, but they cover the majority of the cases I personally deal with on a regular basis. By using PHP in my presentation logic I can create more general and flexible templates and thereby reduce the number of them that I use. And because my template "language" is a full-fledged scripting language (i.e., PHP), I don't have to design my web-sites to the constraints of my presentation layer, because there really are none.

Comments

Updated Template class to PHP 5 syntax

I updated the example code to use the syntax of the PHP 5 Object model.