Templating Engines in PHP

October 07, 2009

This blog post is not for the faint-hearted! Some people will strongly
disagree with me and some others will probably want to kill me at the
upcoming Zend Conference. And
if starting an argument in the comments can help you feel better,
please feel free to do so. If you want to have a more advanced discussion
on this topic, vote for my talk at the Zend
UnConference.

So, you think PHP is a templating engine? So did I... for a very long time.
But recently, I changed my mind. Even if PHP can be used as a templating
engine, the syntax is just plain ugly as a template language.

For several years now, I have been promoting web development best practices,
and one of them is the separation of concerns. Of course, as the lead
developer of symfony, all the projects we work on at Sensio are modeled after
the MVC architecture. It certainly helps when we have big projects where many
people need to work together. The developers work on the code (the Controllers
and the Model) and the web designers work on the design. And templates are
sometimes written by developers, but more often than not, they need to be
written by web designers or by the webmasters themselves.

And a template language is something that helps you to write templates that
respects this separation of concerns. A template language should find a good
balance between giving enough features to ease implementing the presentation
logic, and restricting the advanced features to avoid the business logic to
cripple your templates.

So, when I asked a few days ago about the best and popular templating engines
in PHP on Twitter, some people
naturally answered "PHP" itself. I was not even surprised as that would
probably have been my answer some weeks ago too.

Why do people still think PHP is a templating engine? Sure enough, PHP started
its life as a template language, but it did not evolve like one in the recent
years. If you think PHP is still a template language, can you give me just one
recent change in the PHP language which enhanced PHP as a template language? I
cannot think of one.

Template languages evolved a lot since 1995 and the initial release of
PHP/FI:

Hey, you are using Netscape!

Sorry, that record does not exist

Welcome !

You have credits left in your account.

And as a matter of fact, PHP doesn't support many features modern template
languages should have nowadays.

I will take Django as an example of a modern template language in my examples
for reasons you will understand later on, and mainly because I think Django
template language hits that sweet spot I talked about above.

The following sections describes the main features I want to find in a modern
template language:

This one is mostly a matter of taste, but modern template language have nice
idioms to express common needs. For instance, let's say you want to iterate
over an array and want to display a default text when the array is empty.
That's very common, but the PHP version is not very readable:

*
No item has been found.

The Django version is much better thanks to the use of an else clause for
the for tag:

PHP has greatly evolved over the years as far as reusability is concerned.
Since PHP5, the object implementation is much better, and when
traits will be supported in the
next version of the language, we will have a solid general purpose language at
our disposal. I'm really happy with all these changes as it helps me write
better programs, but these enhancements are irrelevant when what you want to
do is to mainly write templates.

Django introduced template
inheritance some
years ago, as a way to mimic classes but for templates:

I'm not saying PHP is not a secure language, far from it. But needless to say
that escaping a variable in a template is just a nightmare as I have showed
you previously:

Of course, you can create your own function to make it shorter, but that's not
my point:

For me, security should be enabled by default, especially for templates
written by non-developers who are not necessarily aware of the common web
threats like XSS or CSRF.

As far as I know, symfony was one of the very first web frameworks to have
automatic output escaping for variables used in templates (2006); and in the
recent years, major frameworks followed the same path:
Django
has automatic output escaping enabled since 1.0, and Ruby on Rails will also
have it in the upcoming version 3.

Having output escaping enabled by default also means that auditing an
application is much easier. Just have a look at templates where escaping has
been disabled:

Of course, I'm well aware of the automatic output escaping problems.
You still need to take care of escaping variables in JavaScript tags
correctly, but that's much easier to remember than just having to
escape everything by hand.

This one is a must-have when you allow users to edit templates (when
webmasters are allowed to edit some templates from a web backend for
instance). That's not a universal need, but one that needs to be addressed
anyway. Evaluating a template in a sandbox means being able to restrict what
can be done in it. For instance, you should be able to restrict the
methods/functions that can be called, the tags that can be used, ...

Neither PHP nor Django have a sandbox mode, so keep reading this article to
learn more about this topic.

So, I started looking for a template engine that has all the features I
mentioned above. I found many different template engines but none satisfied
all my needs. The next sections talk about some of them and some others people
suggested in reply to my tweet.

As PHP have a million template engines, I have only tested and benchmarked
the more "popular" ones. And as I don't use these libraries, the following
sections can contain wrong information. In such a case, please correct me
in the comments and I will then fix this post accordingly.

PHPTAL is a very nice project that implements the Zope
Page Templates syntax. It is very well designed, supports lots of features,
but is unable to render templates besides HTML ones, which can be a problem if
you want to use the same language for emails, RSS feeds, and so on.

Hello

Also, I think the syntax is not web designer friendly, especially when you use
advanced features like template inheritance:

Calypso is an implementation of the Django
Template Language in PHP. I mention it because it's a clone of Django and
because some people mentioned it on Twitter. But, the author himself
acknowledge that the implementation is
flawed.

When I started looking for a PHP template language, I focused on libraries
trying to mimic the Django template language features. After many hours of
Googling, I found Twig. Twig was written by Armin Ronacher
of Jinja fame. Needless to say I
have the uttermost respect for Armin as he does a wonderful job with Jinja.
As a matter of fact, Twig is more similar to Jinja than Django as far as the
implementation
is concerned.

He wrote Twig back in 2008 for
Chypr, a blogging platform. But he never really developed
it further as he mostly work with Python.

When I had a look at the code, I was immediately sure it was what I was
looking for. The main difference with Calypso being the fact that Twig
compiles the templates down to plain PHP code. I started to use it a bit and
at the end of last week, I asked Armin if he wouldn't mind letting the project
starts a new life. His answer was enthusiastic, and so I began hacking the
code. My version is much different from that of Armin, but the lexer and
parser are mostly the original ones.

I have just hacked the code for a few days, but I'm already quite proud of it,
and I think it's time to open it to the public. So, yesterday I wrote some
documentation for it and put up a
simple website. There is still a lot of work
to do like finishing the documentation, adding more unit tests, and PHPdoc,
but the code is already quite solid and feature-full with:

Very secure sandbox mode (white-list the tags, filters, and methods that
can be used in templates);

Great extensibility: you override everything, even the core features, by
bundling your own tags and filters as an extension; but you can also
manipulate the AST (Abstract Syntax Tree) before compilation. By leveraging
this possibilities, you can even create your own DSL (Domain Specific Language),
targeted at your application.

Despite being one the most full-featured PHP templating engines, Twig is also
the fastest one:

Library

Time (sec)

Memory (Ko)

Templates rendered per second

Twig

3

1,190

3,333

PHPTAL

3.8

2,100

2,632

Dwoo

6.9

1,870

1,449

Smarty 2

12.9

2,350

775

Smarty 3

14.9

3,230

671

Calypso

34.3

620

292

eZ Templates

53

5,850

189

I benchmarked a template that includes a simple template (one output and a for loop on three items) and decorated with a simple layout.
The times are for the average of ten
runs; a run consisting of one compilation
of the template and 10,000 rendering of it. For engines that do not support
inheritance, I have used a header and a footer instead, and for engines that
do not support automatic output escaping, escaping has been done by hand.

When the templates are already compiled, the memory consumption is of course
much better for all template engines, and Twig is the one which uses the less
memory:

Library

Memory without compilation (Ko)

Twig

383

PHPTAL

598

Dwoo

1,645

Smarty 2

1,634

Smarty 3

1,790

Calypso

614

eZ Templates

2,783

If you want to learn more, please visit the Twig
website, and start discussing Twig on its
dedicated mailing-list. If you
want to join the team, subscribe to the
developer mailing-list

I have also planned to talk about Twig at the
Zend UnConference. Vote for this talk
and see you there for an interesting discussion about templating engines.