1. About

Templum is an extremely lightweight, simple yet powerful and fast templating engine for PHP. It re-uses the power of PHP itself for rendering templates, but provides additional features making it easier to write templating code. Rendering templates using Templum is very fast; it approximates native PHP rendering speed for include() statements.

1.1. Features

2. Usage

2.1. API

Templum consists of two main classes.

Templum

The Templum class is the main class that facilitates templates. It retrieves (translated) templates from disk or cache, compiles them and then returns them ready for rendering as a TemplumTemplate class instance.

TemplumTemplate

TemplumTemplate class instances represent templates ready for rendering by your application. They are instantiated by the Templum class, so you shouldn't have to create them yourself. They handle the actual rendering of the template. The TemplumTemplate class also knows how to handle errors in your templates, and has helper functions which can be used from your templates to easily include other templates and to render variabels.

For a complete overview of the API, please see the API reference documentation.

Here's an example that uses just about all of the Templum API, except for Internationalisation:

<?php

require_once('templum.php');

// Configuration.
$pathTemplates = 'view';    // Path where templates live.
$appTitle = 'Hello World';  // Application title.
$author = 'Ferry Boender';  // Application author.
$username = 'jjohnson';     // Currently logged in user (normally from session).

// Create the Templum template engine. The templates live in the 'view'
// directory. We pass one universal variable: the application title.
$templum = new Templum($pathTemplates, compact('appTitle'));

// Turn off automatic escaping of {{ }} contents using htmlspecialchars().
$templum->setAutoEscape(False);

// Set another universal variable.
$templum->setVar('author', $author);

// Retrieve the template with path 'view/account/list.tpl'. We pass the
// $username as a global variable to the template and turn on automatic
// escaping for this template.
$tpl = $templum->template('account/list', compact('username'), True);

// Set another global variable.
$templum->setVar('username', $username);

// Define some data. This would normally come from a database or something.
$accounts = array(
   array('id'=>1, 'username'=>'jjohnson',  'realname'=>'John Johnson'),
   array('id'=>2, 'username'=>'ppeterson', 'realname'=>'Pete Peterson'),
   array('id'=>3, 'username'=>'jdoe',      'realname'=>'John Doe'),
);

// Render the template with the accounts data.
$output = $tpl->render(compact('accounts'));

print($output);
?>

2.2. Template Language

The Templum template language is extremely simple. It re-uses PHP's own alternative syntax for control logic in the templates. It includes some simple special markup that makes it easier to write templates:

{{ and }}

Echo's the variable, function or other PHP printables between the accolades. Echo'ed contents is automatically escaped using htmlspecialchars() (can be turned off).

[[ and ]]

Execute the PHP code between the brackets.

@line

An at sign (@) at the beginning of the line (prepended whitespace is allowed) will cause the entire line to be executed as PHP code.

It is recommended to use the Alternative PHP syntax for control structures (if, while, for, etc) as it greatly enhances the readability of your templates.

An example of a template that uses all available syntax as well as the Alternative PHP syntax:

[[
if (!function_exists('helperBtnAction')) {
   function helperBtnAction($action, $id, $icon) {
      echo('<a href="?action='.$action.'&id='.$id.'">');
      echo('<img src="ico/'.$icon.'.png" alt="'.$icon.'" border="0" />');
      echo('</a>');
   };
};
]]
<h1>User list</h1>

<p>Hello {{$username}}, here's a list of all the users:</p>

<div id="accounts">
   @if (count($accounts) <= 0):
      No accounts found.
   @else:
      <table>
         <tr>
            <th>&nbsp;</th>
            <th>Username</th>
            <th>Full naam</th>
         </tr>
         @foreach ($accounts as $account):
            <tr>
               <td>[[helperBtnAction('account.edit', $account['id'], 'edit')]]</td>
               <td>{{$account['username']}}</td>
               <td>{{$account['realname']}}</td>
            </tr>
         @endforeach
         <tr>
            <td>[[helperBtnAction('account.add', '', 'add')]]</td>
            <td colspan="4">&nbsp;</td>
         </tr>
      </table>
   @endif
</div>

2.3. Variables

Variables can be easily used in your templates. Templum provides three types of variables:

Each of these are explained in the sections below. Templum can generally take variables straight away by passing a paramter containing an array when invoking one of its methods. For instance, we can pass local variables to a template when rendering it:

$username = "jjohnson";
$realname = "John Johnson";

print($tpl->render(array('username' => $username, 'realname' => $realname));

A more convenient way of passing these variables where you do not need to build an entire array each time is the compact() PHP construct. compact() takes string parameters and constructs an associative array for you on the fly. It does so by interpreting the strings you pass as variables from the local scope. Thus the above example can be rewritten as:

$username = "jjohnson";
$realname = "John Johnson";

print($tpl->render(compact('username', 'realname'));

2.3.1. Universal Variables:

Universal variables are variables which will be made available to all the templates you retrieve via a single Templum instance. They are mostly useful for variables which need to be available in your entire application, such as the name of the current user, the application's title, the currently active controller, etc. Naturally you can also assign a helper class which can render common elements of your User Interface to a universal variable and use that from your templates.

Universal variables are set in the constructor of the main Templum template engine class, or at a later stage using the setVar() method on the Templum instance. All templates you retrieve via this Templum instance will have the variables set.

An example:

<?php

require_once('templum.php');

// Define some universal variables
$appTitle = 'My First App';
$username = 'fboender';
$uiElements = new UIElements(); // Helper class

// Create the Templum instance and the universal $appTitle variable.
$templum = new Templum('view', compact('appTitle'));
// Add some more universal variables.
$templum->setVar('username', $username);
$templum->setVar('uiElements', $uiElements);

// Retrieve three templates. $username, $appTitle and $uiElements will be
// available in all three templates.
$tmplHeader = $templum->template('header');
$tmplContent = $templum->template('todo/list');
$tmplFooter = $templum->template('footer');

echo($tmplHeader->render() . $tmplContent->render() . $tmplFooter->render());

?>

The example above defines three variables: $appTitle, $username and $uiElements. It creates a new Templum instance, and immediately passes $appTitle as a universal variable (using the compact() method). It then sets two more universal variables $username and $uiElements. All three of these variables are now available in every template you retrieve using the Templum instance $templum.

You can set additional Universal variables using the Templum→setVar() method of the Templum class. The setVar() method takes two parameters: $varName and $varValue. For example:

$templum->setVar('email', 'j.johnson@example.com');

2.3.2. Global Variables:

Global variables are available to a single template, and any templates that are included by that template. The global variables are set using the $varsGlobal parameter when you ask the Templum class for a template using Templum→template() method. Global variables will be available to the retrieved template and any templates included by that template. Example:

$templum->template('account/info', array(''=>'');

Additional global variables can be set using the TemplumTemplate→setVar() method on templates.

2.3.3. Local Variables

The Local variables are set when rendering the template by specifying the $varsLocal parameter to the TemplumTemplate→render() method. The Local variables will only be available to the template being rendered.

An easy way to pass variables is the PHP compact() function. It takes a list a variable names as strings, and then looks at the current scope and creates an associative array with the variables:

$firstname = 'John';
$lastname = 'Johnson';

var_dump(compact('firstname', 'lastname'));

// Output:
//
// array(2) {
//   ["firstname"]=>
//   string(4) "John"
//   ["lastname"]=>
//   string(7) "Johnson"
// }

Here's an example that sets Universal, Global and Local variables:

<?php

require_once('../../src/templum.php');

$app_title = "MyApp";
$username = "fboender";
$controllerCurrent = "users.list";
$controllerTarget = "users.edit";
$users = array(
        "jjohnson"  => "John Johnson",
        "ppeterson" => "Pete Peterson",
        "jdoe"      => "John Doe"
);

// Universal variable $app_title
$templum = new Templum('view', compact('app_title'));

// Univeral variable $username
$templum->setVar('username', $username);

// Global variable $controllerCurrent
$template = $templum->template('users.list', compact('controllerCurrent'));

// Global variable $controllerTarget
$template->setVar('controllerTarget', $controllerTarget);

// Local variable '$users'
print($template->render(compact('users')));

2.4. Inheritance

Templum features a simple template inheritance scheme which allows a template to inherit from a generic parent template. This works by defining blocks in the parent template which can be overridden by a child template. The inheritance makes it very easy to create a generic layout template which is then filled in by various child templates. The child templates can themselves determine whether they want to be embedded in the generic layout template, making it easy to create multiple different layouts.

Here's an example. First we define a parent template with a generic layout and two blocks: a subtitle and the contents:

<h1>Title</h1>
<h2>[: block subtitle :]Parent template[: endblock :]</h2>

<div id="contents">
[: block contents :]This is the parent contents.[: endblock :]
</div>

Next we define a child template which inherits from the template called parent and which then overrides the subtitle and contents blocks:

[[ $this->inherit('parent'); ]]
[: block subtitle :]child template.[: endblock :]
[: block contents :]
This is the child contents.
[: endblock :]

Now when we render the child template, it will be wrapped in the parent template instead:

<?php
require_once('templum.php');

$templum = new Templum('./views');
$tpl = $templum->template('child');
print($tpl->render());
?>

The output of which is:

<h1>Title</h1>
<h2>child template.</h2>

<div id="contents">
        This is the child contents.
</div>

With this we can be build a complete hierarchy of templates that inherit from eachother, where the parent template is at the top of the hierarchy and the child template is at the bottom. We can create a lower template called grandchild which can inherit from the child template and override a block in that template:

[[ $this->inherit('child'); ]]
[: block contents :]
This is the grandchild contents.
[: endblock :]

When we modify the calling code to call the grandchild template, we get:

<h1>Title</h1>
<h2>child template.</h2>

<div id="contents">
        This is the grandchild contents.
</div>

As you can see, a block is always filled in with the contents defined by the lowest template in the hierarchy that defines that block.

2.5. Including

You can easily include other templates in the current template using the $this→inc() method. Example:

<h1>Title</h1>

<div id="menu">
        @ $this->inc('menu')
</div>
<div id="contents">
        Contents.
</div>

The contents of menu.tpl will then be included.

<ul>
        <li>File
                <ul>
                        <li>Open..</li>
                        <li>Quit</li>
                </ul>
        </li>
</ul>

2.6. Internationalisation (I18N)

Templum provides internationalisation through the use of translated templates. These are simply normal templates with the locale suffixed on the filename. For example:

By default Templum refers to the helloworld.tpl template. You can tell Templum which translation it should use by specifying a locale when instantiating Templum:

$locale = 'nl_NL';
$templum = new Templum('views/', array(), $locale);
$tpl = $templum->template('hellworld');

The example above will retrieve the dutch translation of the template: helloworld.tpl.nl_NL. If no translated template is available Templum will fall back to the default template.

2.7. Errors

2.7.1. PHP v5

The two classes Templum and TemplumTemplate both have their own Exception class:

TemplumError

This exception is thrown by the Templum class when an error occurs such as non-existing templates, etc.

TemplumTemplateError

This exception is thrown by the TemplumTemplate class when errors occur in rendering your template. This includes PHP errors such as uninitialized variables. These errors are intercepted by the TemplumTemplate class and then raised as TemplumTemplateError exceptions.

Fatal errors that occur during template rendering cannot be intercepted by Templum, and therefor show normal PHP errors.

Please see the API documentation for information on which methods throw which exceptions.

2.7.2. PHP v4

The PHP v4 support for errors in Templum is rather limited. Everything is simply handled as a terminal error, and your script will die.

3. Security

3.1. Automatic HTML escaping

Templum tries to enhance the security of your application by automatically escaping HTML entities in output generated using the {{ and }} syntax. You can turn this feature off using the Templum→setAutoEscape(False) method on the Templum instance. This will turn off escaping for all templates retrieved using that Templum instance.

$templum = new Templum('views/');
$templum->setAutoEscape(False);

You can also disable escaping per template by passing False to the $autoEscape parameter of the Templum→template() method like so:

$templum = new Templum('views/');
$tpl = $templum->template('accounts/list', array(), False);

3.2. Eval

Although Templum uses the eval() PHP function, which is generally regarded as an unsafe construct, Templum never evaluates contents that can be influenced from outside the template as it exists on disk. It is therefor not possible for a remote attacker to inject data which might be interpreted as code by Templum. Templum merely translates special constructs such as {{ and }} to PHP code for printing the contents between those constructs. It is therefor just as safe as a normal echo() of a variable.

Care must be taken when dealing with Cross-site scripting attacks though. If you turn off Templum's automatic HTML entities escaping, or use another method of echoing variables than using the {{ and }} syntax, you run the risk of injecting specially crafted HTML or Javascript code into the resulting page. Always properly sanitize any output.