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
-
Lightweight. About 140 lines of code (excluding +/- 140 lines of API comments).
-
Re-uses PHP alternative syntax for clarity and full power.
-
Very fast. Renders 10,000 templates in 0.741s (Native PHP takes
0.633s).
-
I18N (translated) templates.
-
Per-session caching of rendered templates.
-
Inheritance.
-
Security by automatic encoding of HTML entities.
-
Universal, global and local variables.
-
PHP v4 and v5 support.
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.
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> </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"> </td>
</tr>
</table>
@endif
</div>
2.3. Variables
Variables can be easily used in your templates. Templum provides three types
of variables:
-
Universal Variables
-
Global Variables
-
Local 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.
<?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());
?>
<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:
-
helloworld.tpl: Default template, perhaps symlinked to one of the translated versions.
-
helloworld.tpl.en_US: (US) English version of the template.
-
helloworld.tpl.nl_NL: Dutch version of the template.
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.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.