This evening I saw that the most excellent programmer, and lead of the the Symfony Framework: Fabien Potencier, had posted a new article on his blog about Templating Engines in PHP, and announcing a new templating engine: Twig
It’s a good article, and I highly recommend that you all go read it. But I took a few exceptions to some of his arguments against PHP as a templating language itself, I think he grossly undersold PHP-as-template in his enthusiasm to promote his new templating language that he created. This blog post is therefore simply a response to that. To that end, I’d like to start off with a few groundrules for my discussion:
- Fabien’s ideas, and blog post, are solid.
- Twig appears to be a great looking templating language
- While I prefer PHP-as-template, I understand why, and when, using a templating language makes sense
So now, what specific points do I take exception to that he made? Lemme run through them each, in order he presented them:
Verbosity of simply echoing a variable
From his blog:
The PHP language is verbose. You need no less than 14 characters just to output a simple variable (and no, using the more compact <?= shortcut is not an option):
<?php echo $var ?>
Therein lies my first complaint. He’s taken away an option that many consider valid. Yes, it’s long been touted that using short tags, specifically the <? ?> version of them in PHP is considered bad practice. In fact, I agree with them on that specific point. But it overlooks a very common practice. Many developers while shunning the <? ?> shortcut for long blocks of code, still love, and use, the <?= ?> shortcut specifically for templates.
Why do they do this? Simply put, it’s extremely simple, and removes the common complaint that Fabien has brought up. In fact, it is so common, start asking developers and you will find many that cry: “They can pry <?= from my cold dead fingers.”. So common, that there are a number of people (including myself), who have been tossing around the idea of proposing a new option to the short_tags directive for PHP, allowing not just having them turned on or off. But allowing a 3rd option, that would enable <?= ?> while disabling <? ?>
When this is done, The PHP output very closely matches the Django that was used as an example:
| Original: | <?php echo $var ?> |
|---|---|
| Short Tag: | <?= $var ?> |
| Django: | {{ var }} |
Verbosity of output escaping
The article then also includes a discussion of how cumbersome it is to escape output in pure PHP, versus in most templating languages. I actually can’t directly disagree with this one, as even using short tags, you end up with the following comparison:
| PHP: | <?= htmlspecialchars($var, ENT_QUOTES, 'UTF-8') ?> |
|---|---|
| Django: | {{ var|escape }} |
The PHP version is ugly. So what am I arguing here? What I’m arguing, is that the complete premise is incorrect here. It shouldn’t matter how complicated it is to escape inside of the templating language, because you shouldn’t be escaping inside of your templating language.
That statement probably just sat wrong on some people. Afterall, the templating language is supposed to make things easy, right? Well, no. Templating languages are about separation of concern. And specifically in their one truly solid use case – allowing non-programmers to edit templates – are about separating the person editing that file, from any of the code.
Why then, would you trust the escaping of output, something that is vital to the safety and security of your website … to a non-coder who won’t understand those implications? The answer is: You shouldn’t. Therefore it is my opinion that you should be handling all escaping as needed before the data gets to your template. That’s the only way to ensure security. In fact, later in the page Fabien admits to this, stating:
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.
Now where Fabien and I disagree there, is that he believes the solution is just for the templating language to automatically escape everything. I personally dislike this approach, because indiscriminate or inappropriate escaping can cause just as many issues as not escaping in the first place. This is a tricky situation. Not one, IMO, to be left to chance. I therefore greatly prefer having the PHP code itself, handle escaping in appropriate ways. Leave that ‘code’ out of the templates.
Once you’ve taking the escaping out of the template (either via magic escaping or manual), the argument over ugly escaping, disappears.
Legibility of control structures
The argument stays again mostly in the realm of readability, and now turns to more advanced structures. He specifically gives an argument of an example that is very ugly in PHP:
<?php if ($items): ?>
<?php foreach ($items as $item): ?>
* <?php echo $item ?>
<?php endforeach; ?>
<?php else: ?>
No item has been found.
<?php endif; ?>
PHP is a great toolkit, which means there are always a half dozen ways to do anything. That’s great IMO as far as a templating language because it means that I have different options to make something as legible as possible. No matter what. In the above situation, Fabien has taken what is a small control structure with very little text, and written it in, probably, one of the most ugly ways possible to drive the point home. Quite possibly unintentionally. Most programmers would have written that as something like:
<?php
if ($items) {
foreach ($items as $item) {
echo "* {$item}\n";
}
} else {
echo "No item has been found.\n";
}
?>
That’s not only much more readable than the original version to a programmer (and one might argue to anyone), but I even find it more legible than the (granted, smaller) version of this that Django provides, because of having an ‘else’ statement that can be applied to a for loop, from Fabien’s example:
{% for item in items %}
* {{ item }}
{% else %}
No item has been found.
{% endfor %}
Now I realize that I’ve stated that I found it more legible, and I also talked about how a programmer would rewrite this. I realize at this point, I’m starting to cross paths, since didn’t I just say that the one real use-case of a templating language, was for non-programmers? Well yes, and that’s true. But realize that there are other even simpler ways to have accomplished the above. Such as a common trick of separating storing a $noItemsMessage variable if, in fact, no items existed. Allowing it to just be directly output instead of as part of the overarching if/else.
But really, this now leads directly into the next point:
Complexity of language
Fabien talks then about a number of different points, specifically referring to other templating languages, about how they are not powerful enough in many ways. He goes on to give a good example of the power of Django, showing examples of template inheritance, as a way that it mimics class structure inside of the templates.
This is more a failing of other languages, since you can directly mimic Django’s functionality via the use of a few variables and include files, I’ve done it many times. But overall, I think again we start to miss the point and start to run into the other problem when we start discussing templating langauges.
Discussions of creating inheritance, or complicated foreach w/ else statements, seem somewhat moot to me. Afterall, wasn’t the original goal again to have non-programmers writing these templates? Suddenly these are sounding like a programming language altogether. In fact, they are. It’s the common curse of the templating language. It starts as simple. But as people need to perform more complicated tasks for more complicated templates for more complicated websites, the needs of the templating language grows, and suddenly it’s become it’s own programming language, and becomes too complicated for a non-programmer to use, without learning basic programming skills
This point, is where, in my past, serious discussions have happened within organizations over “So who should really be writing these templates now?”.
So now let’s get down to a hard statement by me. It is my own personal opinion, that if you using a templating language, you shouldn’t be doing anything complicated. That defeats the purpose. If people are going to be learning to write code, they should learn PHP and become helpful. Or the control of the templates should pass into the hands of the programmers. And if the templates are in the hands of the programmers, having PHP as your templating language means nothing new to learn, for anyone.
It’s a vicious cycle, I realize, but I keep coming back to it. In general, you should always keep as much code out of your template as possible. There are always ways to structure data to make the template simpler. If you are taking the bulk of logic out of your template therefore, then having a complex language doesn’t matter. (Though, PHP should meet all your complexity needs that you could ever want anyway)
A valid point
So it appears that I’ve completely picked apart Fabien’s article, but I hope that you don’t see it that way. He makes some good points. There are arguments for using his, or any, templating language. But as I started off saying, he seemed overzealous in coming up with good examples, instead of trying to put them on equal grounds.
There is; however, one extremely valid point that he had. What few templating languges offer you, and PHP definitely doesn’t, is sandboxing. The ability to block the template code from doing certain actions. Accessing data it shouldn’t, calling functions that are inappropriate, etc.
If you are in a situation where you absolutely have to let templates be edited by untrusted sources, and being published unvalidated. (Such as letting users of a website edit templates on the fly) Then yes, you absolutely need to find another option besides PHP-as-template
Posted by Eli 

Posted by Eli
Posted by Eli 
PHPAdvent entry: Commenting on Commenting
December 8, 2008Today’s blog post brought to you by PHPAdvent
I was asked to contribute, and so did, polishing off a post I had planned for my own blog and submitting it to PHPAdvent instead.
It’s all about commenting & documenting your code, and you should go read it at the PHPAdvent website.