Choosing the Right Template System for a PHP Web Integration Project
What is a template system? What do I stand to gain and lose if I start using a template system in my web project? What template systems are you using? This article aims to lift the curtain and shed more light on the question of templates and systems for template management.
The PHP programming language was developed almost twenty years ago as an application platform for generating dynamic web pages.
In its relatively long existence it has seen several significant improvements to the internal language structure, especially with the release of PHP 5.0 in 2004, when the new Zend Engine II brought an upgraded object model. The new object model gave an impetus to the creation of a plethora of open source object-oriented web frameworks with MVC (model-view controller) architecture, such as Zend Framework, Symfony, CodeIgniter, CakePHP and Nette Framework, a popular choice in the Czech Republic. Primitive at first, the scripting language adopted terms like "controller" or "DI contrainer" and instantly made programming in PHP a bit more attractive.
The use of PHP in the presentation layer of a dynamic website is fraught with threats that can be avoided by using one of the template systems. In this article I'd like to demonstrate the benefits of using template systems in web applications and also present some aspects of state-of-the-art template systems.
<?php echo $foo; ?>
PHP hasn't seen many new language constructs or syntactic sugar of late, such that would reflect the current requirements and needs of today's front-end developers by either simplifying the syntax of repetitive and frequently used parts of code or by strengthening security, especially through "escaping" the content of variables in order to ensure protection against XSS (cross-site scripting) attacks.
For this reason template systems are being created either as separate pieces of software in the form of reusable libraries (Smarty, Twig) or as integrated parts of web frameworks (Latte). The systems which are inseparably bound with its parent framework are harder to maintain and by definition often unusable on their own. One aspect of the usability of a template system for a web application is its ability to work on its own, i.e. independently of its application framework. A recent trend has been to break down the functionality and to leave it up to the programmer to choose what library he or she will use for the particular project.
Proper documentation in an appropriate extent should be a given. Every open source project that is not sufficiently documented is effectively non-existent.
The deployment and use of template systems often means learning a de-facto new programming language, one that is not designed for the implementation of application logic but rather highly optimised for the use in templates. The syntax of such a language is simple and with high similarity across template systems and also often configurable. The investment needed to study and acquire the basics of one language is partially offset by the applicability of the knowledge to other languages.
An emphasis is put on the secure handling of the content of variables. A majority of template systems allow unified access to the field element as well as the object property. A developer of such a template need not consider the variable type which he or she is accessing.
One of the main reasons for the implementation of a template system is the assistance it provides to the programmer when printing variables with unknown and therefore potentially dangerous content. Mishandling the content of variables can lead to the web application becoming an easy target for XSS attacks. XSS together with SQL Injections are the two most primitive kinds of attacks, the mechanism of which as well as the protection against are well described and documented. Nevertheless, even today we hear from time to time about a massive leak of credentials, in the better scenario, or about a theft of proprietary software or other intellectual property in the worst-case scenario. All of this is because of a failure of a whole link chain of security barriers.
In order to secure a web application against XSS, several measures are recommended (security HTTP headers, content security policy), which cannot be covered in this article. One of such measures is ensuring correct "escaping" of the values of variables that are displayed in response to an http HTTP request. Escaping is a very complicated affair. There is a range of contexts in an (X)HTML template and escaping needs to be done differently in each. PHP itself is not very helpful here and treating the output correctly can be difficult even for highly-skilled programmers, let alone front-end developers or site-builders who configure templates on a daily basis. Ensuring correct escaping is therefore another requirement that a state-of-the-art template system has to meet.
Template systems have different ways of dealing with the question of escaping. There are differences in the number of contexts the systems cover and there are also variances as to whether the systems escape automatically or if this function needs to be enabled manually.
What does "automatic escaping" mean, actually? Although the name suggests a panacea, it means only that all output - unless specified otherwise - will be treated as if it were in an 'html' context. This measure can significantly reduce the risk of an XSS attack, but it cannot eliminate it completely. Even with automatic escaping on, a developer of any template that contains the print of a variable with potentially dangerous content must take into account the context in which the variable will be printed out.
For example Twig distinguishes 5 different contexts ('html', 'js', 'css', 'url', 'html_attr') and in its default configuration automatically escapes all output as in the 'html' context. If a variable is printed in a context other than 'html', there has to be an explicit indication in that specific place in the template to this effect.
Smarty 3.0 covers all basic contexts, but does not escape automatically in the default configuration. Automatic escaping can be enabled, though. Again, it's the programmer's responsibility to decide on the type of context in which he or she will have the variable printed. Similar characteristics can be found in the overwhelming majority of template systems (Twig, Smarty, Dwoo).
For a web application to become vulnerable to XSS, it's enough if escaping has been neglected in one place or a wrong escaping function has been used for treating output.
Separation of Concerns
The use of a template system allows a more efficient elimination of business logic in templates, that is in places where business logic has no business being. Some systems (Twig, FastTemplate) offer a radical solution to this problem - inserting any PHP code in a template is forbidden entirely. In such a template, a developer has to make do with language constructs of the template system. Any complex functionality can be imported to the template using modifiers (filters) or additional functions (helpers). The difficulty of implementing helpers and filters and extensibility in general are some of the key parameters of a template system that are decisive for its applicability in a web project.
Another aspect that helps to separate the application and presentation layers better is "limited scope", a concept implemented across template systems. The practical effect of this concept is that the only "visible" variables in the scope of a template are those that the programmer explicitly declares. The scope of the template is therefore limited and the template itself is only loosely coupledtied to the rest of the application (through the view model), which aids in both reusability and clarity.
Inheritance is another aspect offered by state-of-the-art template systems. There's no specific support for template inheritance in PHP. The template system is therefore fully responsible for it. This makes it possible to use templates to create any complex hierarchies of layouts which can then be used multiple times within one application or across other web projects, thanks to inheritance.
The basic element of a template is a block. A block is a delimited part of HTML which can be rewritten or just extended in any child. The concept of named blocks has been implemented in all known systems (Twig, Smarty, Latte, Dwoo, FastTemplate).
The use of a template system today has only minimal impact on the overall performance of a web application. When choosing a system, speed is a marginal consideration. A state-of-the-art template engine always compiles a source template into the native PHP and uses the compiled version for rendering. If the source template changes, it will automatically re-compile it. Optimisation of compilers is the subject of rapid development and no particular system can be recommended without reservation. There are many benchmarks on the web, but these often lack in objectivity. Regardless, these comparative tests are mostly done with academic constructions that offer very little insight into speed and efficiency, even if the results may vary in orders of magnitude.
In general the simpler a system is, the faster it will be. The same is true of template systems.
A lot has been written about template systems. Currently there's a wide selection of systems that one can choose from. The advantages of using these systems are clearly demonstrated. One may encounter dozens of systems on the web, but Twig and Smarty are mentioned most frequently.
The popularity of Twig owes a great deal to the global popularity of the Symfony web framework of which Twig is a part. Smarty, on the other hand, is a traditional system with a wide user base. In the Czech context Latte has substantial penetration as an integral part of the Nette framework. April of this year saw the release of Nette 2.1.2 in which Latte (a beta version for the time being) can be used separately, which may help in expanding the Latte user base in the future.