Creating Web Page Templates with PHP and Twig (part 1)

Enforced Separation

There’s no shortage of PHP template engines and they’re all very similar, often differing only in implementation details and support for specific features. They all serve the same purpose: that of functionally separating a Web application’s user interface from its business logic, and thereby enabling developers and interface designers to work on the same application without getting in each other’s hair.

Most PHP frameworks, including Zend Framework, Agavi, CakePHP and CodeIgniter, come with built-in templating to enable this separation. However, if you’re not a big fan of frameworks, or if your project is small enough that you don’t need the additional overhead, you can also consider using a standalone template engine to obtain the same benefits. A number of such engines exist – you’ve probably already heard of Smarty, Savant, Dwoo and others – and in this article, I’ll introduce you to one I discovered rather recently, called Twig.

Back to Basics

This tutorial makes a couple of assumptions. First, it assumes that you know the basics of PHP and database programming, and you have a reasonably-good understanding of using objects and object methods in PHP. Second, it assumes that you have an Apache/PHP/MySQL development environment already set up, and that you’ve managed to successfully install Twig. If you’re using the automated PEAR installer, you can install Twig simply by running the following commands at your command prompt:

Alternatively, you can manually install Twig, by downloading it from here. Twig is currently maintained by Sensio Labs and Fabien Potencier, who is also the creator of the Symfony framework, and is released under the new BSD License. This article uses Twig v1.0.

Before you can start using Twig, a quick overview of the basics. Consider that the typical PHP application consists of a number of Web pages, each containing a combination of static HTML elements (navigation menus, lists, images and so on) and dynamic content (data from a database, an XML file, a Web service and so on). Twig provides a way to separate the two, by creating templates containing placeholders for the dynamic content and proving an API to inject “real” content into these placeholders at run-time.

The value for the placeholders are defined inside a controlling PHP script; this script also takes care of the intricacies of database connections and queries, XML processing and additional calculations. Through this process, the Web page is generated by interpolating content from two sources: the template, which contains the static user interface elements and placeholders, and the controlling PHP script, which retrieves data for the placeholders from the appropriate data sources. Programmers and user interface designers are now able to work on the same Web page simultaneously, without needing significant additional coordination (apart from agreeing on the names of the common placeholder variables).

Locked and Loaded

To see how this works, here’s a simple illustrative template:

Save this file as templates/thanks.tpl. Notice that the placeholder variables are surrounded by two sets of curly braces; this tells Twig that they are template variables and must be replaced with actual values at run-time.

Next, create a controller script that populates these variables with actual data and renders the composite output:

And now, when you access this PHP script through a browser, you should see something like this:

There’s a fairly standard sequence to rendering a template using Twig:

  1. Initialize the Twig autoloader. This registers the Twig autoloader with PHP, so that Twig classes and plugin files are automatically found and loaded as needed.
  2. Initialize a template loader. This is done by creating an instance of a class which implements the Twig_LoaderInterface – in this case, the Twig_Loader_Filesystem. The object constructor is passed the name of the directory in which to look for templates.
  3. Initialize the Twig environment. This is done by creating an instance of Twig_Environment, which stores the current Twig configuration.
  4. Load a template. The environment object exposes a loadTemplate() method, which can be passed a template file name and which finds and loads the relevant template into memory. The return value of this method is a template instance.
  5. Set values for template variables and render the template. A new associative array, whose values correspond to template variable names, should be defined and then passed to the template object’s render() method. The render() method interpolates the values from the data array into the template object, generating and rendering the composite result.

Getting Even

Twig also lets you conditionally display content within a template, through its ‘if-else-endif’ control structure. Here’s a simple example of a template that uses this structure:

Depending on the number generated within the PHP controller script, the template will display one of two possible messages. Here’s the controller script, which randomly picks a number between 0 and 30, and then divides it by 2 to check whether it’s odd or even:

Here’s a sample of the output:

You can also handle multiple conditions within a Twig template, through the ‘if-elseif-else-endif’ control structure. Here’s an example of a template that uses this:

And here’s the PHP controller script, which retrieves the current month number and passes it along to the template:

Here’s an example of the output:

Looping The Loop

Twig also supports ‘for’ loops, allowing you to repeat a particular block of a template over and over again. This is quite handy, especially when looping over arrays. To illustrate, consider the following template:

In this template, items is an indexed array, which is populated by the PHP controller script. On each iteration, the current element of the array is assigned to the local loop variable item and printed as a list item. Here’s the PHP controller script, which sets up the items array:

And here’s what the output looks like:

Twig also supports so-called “dot notation” for accessing the keys of an associative array or the properties of an object. To illustrate, consider the following PHp controller script, which defines an associative array of values and passes them to a Twig template:

Within the template, the keys of the associative array can be accessed by suffixing the template variable name with a period and the key name, as shown below:

Here’s what the output looks like:

This also works with objects…as you’ll see on the next page!

Data Dump

The ability to use loops inside template comes in particularly handy when you need to integrate the results of a database query into your output template. To illustrate, consider the following template for a five-column table:

This template is populated with the following PHP script, which uses PDO to connect to the MySQL ‘world’ database, retrieve a list of countries and cities, and package this data into a template variable:

Notice two things about the above listing:

PDO’s fetchObject() method is used to return each row of the database result set as an object, whose properties correspond to column names. These row objects are then placed in an array, and passed to the Twig template. Within the template, dot notation is used to access the individual columns of each row and print the corresponding values.

This template make use of a built-in Twig filter, ‘escape’, which takes care of automatically escaping output before printing it. You should filter all output in this manner to reduce your vulnerability to XSS attacks. By default, the ‘escape’ filter escapes output using PHP’s htmlspecialchars() function.

Here’s what the output looks like:

Some Assembly Required

Twig also comes with an ‘include’ statement, which can be used to load templates from other files into a container template. This is handy when you have common page elements, like menus or header/footer bars, and you want to use them multiple times, but maintain them in a single location.

To illustrate how this works, consider the following top-level template, which internally makes use of three separate sub-templates:

Three sections of this page – the primary header menu, the secondary left menu, and the page footer – are loaded from separate template files via Twig’s ‘include’ statement. Here’s what each of these looks like:

And here’s the PHP controller script that brings it all together:

Notice that it isn’t necessary to call loadTemplate() for each of the individual sub-templates; all that’s needed is to call the top-level template and that template will, in turn, load each individual sub-template as needed. Variables defined in the PHP controller script can be accessed by the individual sub-templates as well.

Here’s an example of what the output looks like:

Filter Fever

Twig comes with a bunch of built-in filters that you can use to perform quick-and-dirty manipulation of template content. Needless to say, you can also define your own filters (a topic that’s covered later in this tutorial).

First up, the ‘date’ filter. This filter makes it possible to format dates and times using standard PHP date format specifiers. Here’s an example:

Here’s a sample of the output:

You can also alter the case of template variables using the ‘upper’, ‘lower’, ‘capitalize’ and ‘title’ filters. Here’s an example that demonstrates:

Here’s what the output looks like:

The ‘striptags’ filter removes all the HTML and XML tags from a template variable, as shown below:

Here’s the stripped output:

The ‘replace’ filter provides an easy to perform in-place string replacement. It accepts a hash of key-value pairs, and replaces all the keys in the string with the corresponding values. Here’s an example:

Here’s what the output looks like:

You’ve already seen the ‘escape’ filter in use earlier, but there’s also a ‘raw’ filter which does the opposite: allows HTML code to pass through unsanitized. Remember that this should only be used on input that you’re completely sure is safe. Here’s an example:

Here’s what the output looks like:

If you have a large block of text to be escaped or unescaped, you can also enclose it within an ‘autoescape’ block, passing a Boolean true/false argument to turn escaping on or off. Here’s an example, which is equivalent to the previous one:

At this point, you should have a good idea of the basics of using Twig, together with a broad understanding of available control structures and filters. In the second and final part of this article, I’ll go a little deeper, looking into Twig’s more advanced features, such as template inheritance, custom extensions, configuration and much more. Make sure you come back for that…and happy coding!

Copyright Melonfire, 2011. All rights reserved.