PHP, Zend Framework and Other Crazy Stuff
Archive for October 9, 2009
Is PHP A Worthy Template Language? Well, of course it is…
Oct 9th
A few days ago, Fabien Potencier published the article Templating Engines in PHP in which he argued against using PHP as a template language in favour of a non-native template language. However, let not the title or opening content depress too much. Fabien was, after all, opening this door for a specific cause – a templating solution called Twig he is actively developing. If the article were not enough, it is also repeated on the Twig website.
So why write my own article in response?
Fabien’s article triggered the urge once again to challenge the status quo, the continued view of something in PHP being necessary when in truth it simply isn’t. The article takes that view to extremes, going to some effort arguing against the recent slide towards templating with PHP with arguments which are so biased as to misinform readers. I do two things when I meet a status quo and a biased view I disagree with. I a) write a bunch of source code and engage in a hit or miss affair to see if someone else will use it, b) write another laborious blog post on some facet of PHP development (currently Asynchronous Processing), or c) I rant the bejesus out of something. Today, I’m ranting a little bit.
Before I start, I figured I’d share my main observation about Fabien’s article. There are two facets to it. The first is that Fabien is actively developing and publicising a templating solution called Twig. It’s mentioned over half way through the article generically titled “Templating Engines in PHP” but never alluded to up front. The second is a common debating tactic. Well, actually it’s several so I’ll summarise them as a broad unified strategy:
The single most powerful tool in the arsenal of a blogger is the act of omission. For example, you present an obvious fact that is devastatingly negative, and follow that up by dismissing the obvious solution out of hand and refusing to admit it even exists. Now, your original argument is solidified in the minds of your readers preparing them for your solution as the only saving grace. It also works just as well in reverse.
Fabien’s article uses this strategy more than a few times. If nothing else will provoke a response from a community, using this tactic is guaranteed to for a reason. Simply stating what is being omitted or dismissed out of hand is an easy retort. So here’s mine. You can also read the always dependable Eli White’s In Response to Fabien Potencier: Twig & PHP Templating which will, no doubt, be far more neutral than my response. Remember, I’m ranting here
.
The original article, commences the topic of “Templating Engines in PHP” by attacking PHP itself as a templating language. To explain, you have two broad options for a templating language. Use native PHP itself, or use a parsed language like Smarty’s tags. There has been debate about which is superior for years and, in recent years, PHP has been gaining ground most likely due to the fact that PHP 5′s object oriented improvements have made a PHP oriented templating solutions simple to implement. The second reason for the upsurge is the rise of web application frameworks who have discovered PHP makes sense as a templating language. I’ll direct you to Zend_View from the Zend Framework as an example.
In Fabien’s arguments a few points are made which I’ll address in turn.
1. The PHP language is verbose
PHP has always been a verbose language, and this can be demonstrated by using full PHP syntax in a template.
[geshi lang=php]var, ENT_QUOTES, ‘UTF-8′); ?>[/geshi]
Using long PHP tags, and the full escaping mechanism, the statement length is attrocious. By demonstrating this, Fabien argues that the verbosity of PHP makes it a poor choice as a templating language. However, this is not entirely accurate. If you enjoy writing PHP code, you probably know of a few shortcuts. Personally, since any templating language worth a damn has an overarching support framework, i.e. the actual templating library, I prefer to write this as:
[geshi lang=php]= $this->var ?>[/geshi]
This is achieved using three common tactics.
First, use a templating library…unless you enjoy torture. PHP requires structure. Without it, you really would be writing Fabien’s example a thousand times over. Zend_View offers a ridiculously simple mechanic of including templates (basically snippets of PHP) into the method of an object. This means that all templates exist within an object, i.e. the templates become bound to the object oriented nature of PHP. That’s why my template variables are prefixed with $this. Also, Zend_View’s basic templating is contained in a single class, most of which is pathing and other setup.
Second, use short tags! Fabien states “using the more compact shortcut is not an option”. Pity it’s not true. You can use short tags. Hell, you can even use short tags on systems where they are disabled in php.ini, because a good templating library can enforce them using a PHP stream intercept (Zend_View supports this). Granted, as a workaround, it costs a little bit of performance but it’s worth it for the brevity. If you are really worried about compatibility in a distributed application, use a deployment task to rewrite the short tags into long tags. It’s not the most difficult compromise imaginable.
The other part of Fabien’s dismissal is the rumoured removal of short tags support. Personally, I think this will never happen and at most will see a replacement. The benefits of short tags have shifted from their original purpose and are now a compelling reason for using PHP as a template language. Removing support for it would be a major disappointment and a major setback for anyone already using this syntax. But let not mere future possibilities colour what you can do here and now from the safety of PHP 5. PHP 6 is a long long way in the future. As for short tags being horrible practice – screw that. They are simple, easy to write, effective, and controllable when applied only to templates (not other source code files), and have existed for years. The trick is keeping them around only for templates.
Third, never openly escape variables in templates. Do it in the background automatically. This sometimes called the Poka-Yoke principle and I blogged about it way back in January 2007. It’s also going to be adopted in Zend Framework 2.0 but can be marginally achieved right now with a teeny bit of coding unless you’re using one of the frameworks which already do have it. The main addition I’d note is the capacity to deliberately access the non-escaped value. This is safer – deliberately bypassing escaping requires…well…deliberate action. Escaping automatically has two benefits. You won’t have to type manual escaping calls into templates, and you’ll have far less of a chance that someone forgets to escape a variable.
The PHP language is verbose…but it’s easy to implement brevity as a feature.
2. The PHP language is not very readable
People have been saying that for years. Then they see C++ and thank whatever God they believe in. PHP is readable, so long as you remember that it is, indeed, PHP. You can make it completely unreadable by refusing to apply common sense and a decent coding standard. Fabien demonstrates his point by abandoning all common sense, giving rise to this monstrosity:
[geshi lang=php]
*
No item has been found.
[/geshi]
Ignoring for the moment the capability to just write a list View Helper which would reduce this to four lines of code, you could rewrite the entire thing far more elegantly as proposed by Eli White in his own response:
[geshi lang=php]if ($items) {
foreach ($items as $item) {
echo “* {$item}\n”;
}
} else {
echo “No item has been found.\n”;
}[/geshi]
Me? I’d just stick it in a reusable View Helper as a generic List Helper. How many times do I need foreach myself to death before a reusable class becomes compelling? Depends – everyone has a different tolerance
.
3. The PHP language is less secure than a templating language
I’ve already covered a lot of what Fabien raised for this point by indicating the existence of the Poka-Yoke strategy. PHP does not allow for this by itself – it requires a structure, i.e. a templating library or class, which can implement it.
Fabien, also notes that PHP does not have a “sandbox” mode. This, presumably, is to selectively prevent the use of certain PHP functions which are deemed unsafe (I’m sure there’s tons more could be done here too). You see this protection most often when templates are either a) edited by public users or untrusted administrators (distrust may refer to ability rather than some sense they’ll deliberately attempt to break something), or b) edited by untrusted web designers. This is probably the single most compelling argument for a non-PHP templating language which by its nature constricts access to PHP itself. However, there is a solution depending on your requirements. PHP’s Tokenizer.
The Tokenizer can parse any PHP you throw at it, creating a complete breakdown of the PHP code which is then easily searched for anything including blacklisted/illegal function calls (or the alternative, confirming the presence only of whitelisted elements). Whether you do it from within the interface of a web application, or using a build/testing tool to drive it, it’s fundamentally simple to implement. However this does not offer any runtime protection as described – this is more a validation tool (a simple extension to the principle of never trusting user input
). You could implement it at runtime, but whether you need to constantly check every template before it’s used is up to whoever needs this feature.
Yes, I know this is not a perfect sandbox – your mileage may vary.
4. The PHP language does not offer template inheritance
Or as Fabien states:
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.
If you were to design a library where all classes inherited from every other class, you would probably be shot by Martin Fowler. Either that, or Kent Beck would do something while roaring what suspiciously sounds like “Hulk! Smash!”. Fortunately, there is an alternative. A wee little thing we like to call composition.
Composition is an incredibly powerful tactic in any object oriented programming, and that is completely and utterly relevant when it comes to templates written in PHP. Inheritance is the poor man’s substitute since, unlike composition which acts to an agreed interface allowing the easy substitution of objects, inheritance creates dependencies on parents. What does inheritance buy in terms of reusable templates? Partials, Placeholders, Layouts, View Helpers, etc.? These are all easily implemented in PHP using COMPOSITION as evidenced by Zend_View and it’s counterparts in other frameworks. This is hardly irrelevant!
Further, inheritance demands the declaration of the inheritance tree, so my templates are now littered with hard coded references to template after template. The fact is, composition has always been more compelling and it won the war against blind multi-tiered inheritance years ago. It lost because it created more problems than it solved by generating a mass dependency effect that resisted change and quickly became inflexible and unmanageable.
No, composition is definitely relevant. Using it, a PHP templating solution can quickly create a flexible template API. It’s not often mentioned, but a template API is something few people realise they are creating by adding View Helpers. Afterall, the whole concept of a View Helper is to deliberately simplify the application of PHP to the domain of templates, to leverage the PHP language to reduce complex presentational logic that is long winded, and hard to read, to something easier to grasp and reliably document for future use. That simplification makes it easier to write short handed templates, and easier for a designer minimally trained in PHP to get to work without masses of complex PHP code getting in the way.
I think this dovetails nicely with something Eli White said which I couldn’t agree with more:
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.
Simplicity is key. A deliberate attention to building up a documented API so all your nice View Helpers make sense to a designer is worth a little sunk time if it keeps the design wheels churning on something helpful rather then struggling with a few dozen undocumented helpers whose purpose is unclear.
Now I’ve gone overboard, a bit, with this section for a reason. You should never see PHP as a template language sitting alone. It should always have a library attached or, at the very least, an. There is a huge difference to using PHP as your templating solution and using it as a templating language. It’s only a templating solution when you create a library to allow it to remain concise, flexible and capable of the features a templating solution should have as standard.
Twig is really fast?
My response in this blog post is not a rant against Twig, but against the opening gambit of Fabien’s article which is designed to dispell any notion that PHP is a worthy templating language (i.e. a competitor to Twig particularly dominant in web application frameworks). Nevertheless, if we are going to compare templating solutions it would be nice to compare Twig against something that actually does use PHP as a templating language, like the Zend Framework’s Zend_View.
To this end, I spent a bit of time getting to know Twig and created a simple benchmark test. Which you can take a peek at on github at TwigVsZF and criticise to your heart’s content. The benchmark is a simple affair with two base files: twig.php and zf.php. Both are left at their default configuration with the exception that Twig is configured to use a cache directory for its final compiled PHP code. Both are also configured for their template locations. Otherwise, escaping follows each option’s apparent default operation. So Zend_View uses manual escaping and Twig’s auto escaping is enabled. Otherwise, the templates for both are mirror images except for the obvious syntax differences. The template used is a simple HTML page, with a loop to construct a navigation menu with three entries.
To measure their respective performance, I just looped 10,000 times around the relevant code needed to render a template and took the total time as the basis for the calculations. It was performed a few times, simply by calling the relevant script from the command line, to get a reasonable average.
The results for rendering a template 10,000 times?
Twig:
Total Time (s): 2.74
Templates (p/s): 3647.18
Zend_View:
Total Time (s): 3.75
Templates (p/s): 2664.56
Twig clearly is extremely fast which strongly reflects its lean design. Zend_View’s primary slowdown lies in a few design decisions in how it parses options and sets up initial paths. The first could be improved to narrow the margin of difference quite a bit but since we’re essentially hitting the territory of microseconds, it will probably never happen.
I have few reservations about saying that Twig is definitely a templating solution to watch if you are not of the PHP-is-a-template-language persuasion. I didn’t have time to assess how easy it was to build in custom helper tags (the equivelant of ZF’s View Helpers in a tag based language) but I’m sure it wouldn’t be that hard.
The article should have stuck to introducing Twig, it stands by itself pretty well and simply did not need the distraction of a poorly one-sided argument against PHP as a templating language.
