The Wheel: Twig

DZone 's Guide to

The Wheel: Twig

· Web Dev Zone ·
Free Resource

A question that comes up cyclically every year in the PHP community: do we need a templating language for PHP or the language itself is already practical enough that you can write view in plain PHP? For the ones who think the first option is the correct answer, Twig is a good choice for the language itself.

Why adopting Twig?

Twig is an open source tool that takes templates written in its language, compiles them to PHP 5.2 (and as such run everywhere), and renders them to HTML or whatever markup you're targeting. As always, it is installable from Composer and makes use of its autoloader, and the composer.json says there are no dependencies to other Symfony Components.

Twig is yet another templating solution; however, it is interesting because it's the tool of choice for the Symfony 2 ecosystem. Even while being developed inside Symfony, it has no tie to the framework as a whole, and can be installed and run in isolation. Its API is all you need, making you create a graph with only two externally visible objects in order to render all of your application.

Here are two simple examples from the official documentation. The first is for rendering strings containing the template:

$loader = new Twig_Loader_String();
$twig = new Twig_Environment($loader);

echo $twig->render('Hello {{ name }}!', array('name' => 'Fabien'));

While the second provides a little more (neutral) abstraction by supporting the loading of templates from a specified directory:

$loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
  'cache' => '/path/to/compilation_cache',

echo $twig->render('index.html', array('name' => 'Fabien'));

One of the cases where testability leads to a more flexible design, like one in which you can render user-generated templates coming from a database. Going back to the template systems of just some years ago, I experienced many difficulties in finding the same functionality, usually hidden or not supported. Separation of concerns makes this simple in Twig (while you can always render strings, Twig provides Inversion of Control too by exposing a Twig_LoaderInterface that you can implement for these cases).

For what regards the actual syntax:

<p>Hello, {{ name }}</p>
{% for topic, messages in topics %}
  <li>{{ loop.index }}: {{ topic }}</li>
{% endfor %}

A feel of the GitHub repository

Twig's repository feels modern, by 2013 standards, like for many of the Symfony components. Automated tests are present and target mostly the unit level, with some integration ones that work on real templates.

While the unit tests are written with PHPUnit, the integration tests are run inside PHPUnit but written with an extension of phpt's syntax. We are looking at a ratio of 6K lines of tests on 14k lines of code, which is acceptable for an open source project (you can always give back to the project and contribute some tests where coverage is lacking).

Moreover, there is a strong documentation at the docblock level and a comprehensive end user manual, containing also several FAQs in the form of recipes for using Twig for certain goals. The Symfony community is behind the project and this can only be good for the long life of the product.

I noticed there is a C extension  for the PHP interpreter that can improve Twig performances where needed, such as in websites where outputting content is the main job. I wonder how the developers keep the PHP source code and the C extension in sync, but I saw only one PHP_FUNCTION macro in the C code, so it's probably still under development.

Philosophical considerations

If you need a template language, the diffusion of Twig and its surrounding Symfony ecosystem suggests adoption over any other legacy library (see Smarty). However, the question remains open if it is possible to use PHP itself successfully as for this goal.

On one side, Twig has an overhead, both in performance, in its learning curve, and in the 14K lines of code of complexity that is added to your application. On the other hand, I see these tools as forcing separation of concerns, business logic versus presentation, as much as Behat steps force separation of automation and specification.

The hello world code earlier in this article of course wouldn't benefit from using Twig, like all introductory examples:

<p>Hello, <?=$name ?></p>
<? foreach ($topics as $index => $topic) { ?>
  <li><?=$index ?>: <?=$topic ?></li>
<? } ?>

But as complexity goes up, you find out include() is not always the best way to remove duplication. As long as you're not going in the View Objects direction, where your markup is generated by an object graph, I would suggest a standard templating solution to avoid losing energy and time on an aspect that is not your competitive advantage, such as the organization of HTML output.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}