Templating Engines in PHP
Fabien Potencier
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 PHP is not (anymore) a good template language?
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 :
<!--include /text/header.html-->
<!--getenv HTTP_USER_AGENT-->
<!--ifsubstr $exec_result Mozilla-->
Hey, you are using Netscape!<p>
<!--endif-->
<!--sql database select * from table where user='$username'-->
<!--ifless $numentries 1-->
Sorry, that record does not exist<p>
<!--endif exit-->
Welcome <!--$user-->!<p>
You have <!--$index:0--> credits left in your account.<p>
<!--include /text/footer.html-->
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:
Concision
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
?>
And PHP becomes ridiculously verbose when it comes to output escaping (and yes, escaping variables coming from an unsafe source is mandatory nowadays):
<?php
echo
htmlspecialchars
(
$var
, ENT_QUOTES, 'UTF-8'
)
?>
Compare with the same examples written with the Django template language:
{{ var }}
{{ var|escape }}
Template oriented syntax
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:
<?php
if
(
$items
)
: ?>
<?php
foreach
(
$items
as
$item
)
: ?>
* <?php
echo
$item
?>
<?php
endforeach
; ?>
<?php
else
: ?>
No item has been found.
<?php
endif
; ?>
The Django version is much better thanks to the use of an else
clause for the for
tag:
{
% for
item in items %}
* {
{
item }
}
{
% else
%}
No item has been found.
{
% endfor
%}
Reusability
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:
<!-- base.html -->
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
{% block head %}
<link rel="stylesheet" href="main.css" />
{% endblock %}
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
<!-- index.html -->
{% extends "base.html" %}
{% block head %}
{{ block.super }}
<link rel="stylesheet" href="main.css" />
{% endblock %}
{% block content %}
Index content
{% endblock %}
It's elegant, easy to understand, and really powerful. It's so powerful that many template engines now support this feature out of the box.
Security
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:
<?php
echo
htmlspecialchars
(
$var
, ENT_QUOTES, 'UTF-8'
)
?>
Of course, you can create your own function to make it shorter, but that's not my point:
<?php
echo
e(
$var
)
?>
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:
{% autoescape off %}
{{ object.as_html }}
{% endautoescape %}
{{ object.as_html|safe }}
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.
Sandbox mode
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.
Alternative template languages in PHP
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.
Smarty and Smarty 3
That's the first one that comes to mind. And Django template language itself was inspired by Smarty . Smarty is the de-facto PHP standard template engine.
Hello {
$name
|escape}
{
section name=item loop=$items
}
{
$items
[
item]
|escape}
{
/section}
But Smarty suffers from several problems:
- Not object oriented
- No template inheritance
- No sandbox mode
- No automatic escaping
As far I understand, Smarty 3 is just around the corner and will improve the library quite a lot:
- Object oriented architecture
- Auto escaping of variables
- Template inheritance
I tested the two versions, but the performance of both are quite bad (see at the end of this post for more information on the benchmark I did).
PHPTAL
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.
<?xml version ="1.0" ?>
<html>
<body>
Hello <span tal:content ="name" />
<ul tal:repeat ="item items" >
<li tal:content ="item" > </li>
</ul>
</body>
</html>
Also, I think the syntax is not web designer friendly, especially when you use advanced features like template inheritance:
<html metal:use-macro ="layout.xml/main" >
<body metal:fill-slot ="content" >
Hello <span tal:content ="name" />
<ul tal:repeat ="a array" >
<li tal:content ="a" > </li>
</ul>
</body>
</html>
<html metal:define-macro ="main" >
<metal:block define-slot ="content" />
</html>
One of the biggest selling point of PHPTAL is the autocompletion you can have in IDEs, and a guarantee that your HTML is well-formed.
eZ Components Templates
eZ Components Template Component is also a very nice implementation of a template language. It's probably the one which have the most features... perhaps too many of them if you ask me:
{
use $name
}
{
use $items
}
Hello {
$name
}
{
foreach
$items
as
$item
}
* {
$item
}
{
/foreach
}
It does not support template inheritance, and my main concern is the performance. This it is the slowest library I have tested, and by great margin.
Dwoo
Dwoo is an interesting project. It is positioned as an alternative to Smarty. And they did a great job:
<html>
<body>
{
block "content"
}
{
/block}
</body>
</html>
{
extends
"layout.tpl"
}
{
block "content"
}
{
include
(
"basic.tpl"
)
}
{
/block}
Dwoo mimics Smarty but with some interesting new features like template inheritance, and with much better performance than Smarty.
Unfortunately, Dwoo has no sandbox feature and its core is not flexible enough.
Calypso
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 .
Twig
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:
-
Native template inheritance (templates are compiled as classes);
-
Solid automatic auto-escaping (with no associated runtime overhead as everything is done during compilation);
-
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.
A couple of years ago, someone asked me "Why are you using a template engine when PHP is a template engine?". I gave it some thought, and they were right. What is the point in adding another layer of processing? So, I abandoned Smarty.
However, after using Symfony for the past year or so, I've actually been starting to think they're not such a bad idea.
Not only does it make the template editable for non-developers, but it also makes the template a hell of a lot more readable.
@Celso: It will probably be part of Symfony 2. But I first need some community feedback.
I just read some documentation on the official site and I feel good with the syntax so close to Smarty that I use since 4 years.
Great work!
how does it fit with http://components.symfony-project.org/templating/
Are there any plans to integrate them?
Yes, you need to check short_open_tag is enabled, but I'd argue that's not a problem for the vast majority of framework users; they have other configuration requirements anyway.
I'm sure you've done the math: the extra verbosity comes down to two characters if you're in control of your own setup. (<?= $var ?>)
What are some of the things I'd like to see in a modern templating language? How about familiarity for a huge percentage of developers and designers? How about IDE auto-completion? (I'm really going to miss that.) How about being able to step through templates in a debugger?
"and Twig is the one which uses the less->least memory:"
Thanks for another great contribution to the PHP community!
I've got a point which is not really discussed in this article and which is, I think, very important:
When working with a graphic team in charge of the integration of the website's pages you must have a template system easy to use for a non-coder person. I think flow control and loops are to complicated in the template engines listed in this article. Designers don't have to know the use of FOR AS structures. phpBB template Engine uses BEGIN/END key words which I found more handy.
An other point is cache. Template engine could handle caching portions of web pages.
That's why, from my point of view, template engines listed above are not perfect.
A templating system - like Symfony already has - is a very good idea. Built in output escaping is great. Template inheritance looks interesting. But I would like to see these features implemented in a system that uses PHP as its base language. I don't buy the separation of concerns argument. If you have to force people to program well then they'll just find another way to break things.
I noticed your intending style. Not sure how smart your blog is about whitespace, but here is an example:
<html>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
I think it makes sense to not care about the html intenting level for control flow. Instead I "maintain" separate intenting levels for all control flow in my code:
<html>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<? if ($user->isLoggedIn()): ?>
<p>Hello <?=$user->getName()?>!</p>
<? else: ?>
<p>Please log in</p>
<? endif; ?>
Looking at the PHPTal syntax, that is going to be definitely more verbose, than the PHP one.
I'm completely against the "designers don't have to know about foreach and stuff" mentality. They should totally know about it. It is a very simple, and easy to understand concept. Saying that one engine's way of doing a foreach is nicer for a designer, is not reason enough.
Looking at the PHPTal syntax, I'm not entirely convinced that it is really easier to read for someone that is unfamiliar with PHP code, than the pure PHP syntax.
You make a very good point about template inheritance, that is something that I'm missing from pure PHP templating. It can be implemented, but it never will be as nice as in the examples above.
Thank you for the article, it was a very good read, but I'm not convinced yet :)
Is traits really coming with the next version? I was so sad when I saw that it wasn't coming with 5.3 :(
I in all honestly think template engines are garbage. I hate the fact that you have to basically "learn" a new language and syntax that can be easily written out as PHP. Secondly it will be slower then using regular PHP because it will have tons of parsing and possible regex to process. Thirdly its lack of support for the most basic of tasks, like not being able to use all of PHPs built in functions, is a total pain.
Additionally the theory everyone says "Frontend/Designers who don't know PHP should have an easier time writing and using the template engine" is just totally retarded in my opinion. Why subject them to such an inferior system when they could learn basic PHP alongside developing the templates? Its not hard to learn loops, if statements, expressions and conditionals... especially if they already know Javascript.
It also seems your only major gripes with using regular PHP is having to write more characters/more code. Like in your example about escaping, sure |escape is shorter to write and easier to do, but what if you want to customize the ouput and not use UTF-8? For example Smarty:
{$var|escape:ENT_QUOTES,"ISOxxx"}
I don't honestly see a benefit in that, if anything it looks uglier and harder to read.
However ill give you the benefit of the doubt cause you built Symfony, so Ill give Twig a try.
I went from a different templating language over to using PHP, and found it to be a huge improvement on all fronts. You're right though that it does tend to be verbose though. It would be great though if PHP itself was improved to be a better templating language. Maybe even a core template extension to enable sandboxing, etc?
All the best with Twig. Had a quick peek at the docs. It's got some pretty nifty features. You might be making me swap to the dark side again.... :-P
From my experience, graphic designers that would not be able to work with a PHP template would not feel any better working with a Smarty or other template. Its a great idea to run the MVC model, but I am not doing it for the designers as they usually get confused pretty fast and scared with so many different files.
Oh course I am a little odd when it comes to executing the "content" template. When I am not working with symfony I usually will use the output buffer ob_start() to run the "template" php file using an include() or require(), not inside of any functions or classes. This gives me (a programmer) full access to any classes and variables that are part of the program without having to pass them to a template class or function. Once the content "template" is done executing I store the output buffer to a variable and then execute the layout "template". Again I know I take a different approach then most developers, but I like to keep stuff simple, fast and effective.
@Miles Johnson - Totally agree with you.
If Symfony 2.0 forces the use of a template engine I will be back to looking for a framework, I know I am not going to change the symfony developers mind by making this statement, but you asked for feedback and here it is.
* AFAIK short tags can be set per directory
* Escape data BEFORE passing it to the template or implement aliases/shorthand functions, var_export for those who can't bear writing "$this->"
* Who uses "sandbox" mode anyway, I mean, if your designers don't follow your instructions, fix the process not the tool..
* Simple, short, very readable, super fast (with APC):
<? if empty($items) { ?>
No item has been found.
<? } else foreach ($items as $item) { ?>
* <?= h($item) ?>
<? } ?>
* Inheritance can be implemented with simple includes or keeping a stack of templates to execute, passing the generated content to the next template in the stack.
* And when you do need to add some new functionality, it's almost always going to be faster in plain PHP (unless your the author of that templating languge)
{$var|escape:$smarty.const.ENT_QUOTES,"ISOxxx"}
The Smarty syntax is not that bad, it just lacks support for widely used PHP features (constants, objects, static objects...). And Smarty code is really really a pain to read with very long regexps. And you can't use the parser for other things than compiling. Quite a pain too. And it's slow.
See http://blogs.kd2.org/bohwaz/?2009/09/30/297-smarty-vs-smarty-3-vs-template-lite-vs-dwoo fo some benchs between Smarty 2, 3, Template Lite and Dwoo.
When I found out about this through a github update I hadn't noticed you had already blogged
* Are you secretly a robot from out of space? Given the amount of projects you manage to run next to your company I sometimes think so
* What will the relation of Twig have to the Symfony 2 release? I take it it can be hooked into the new templating component as a template renderer right?
* Just out of curiosity, why didn't you market this as an Symfony component?
And now in response to some of the comments made here. I never used a templating language since I started to work for myself. My last templating engine experience was freehand for Java and it was a bloody nightmare. For PHP I never found a good one neither the need to write one. This blog post, and more so the code of Twig made me think differently. The architecture enables easy additions of required language elements on a per client bases and the sandboxing is really nice for projects where users are allowed to create templates.
The combination of that opens up a whole new world of possibilities for some CMS systems I deploy to different clients.
Now sure this will add another stack of learning but come-on, we are developers, we're not stupid right and most of us are eager to learn. And if your front end developers can't learn a for each statement I'd talk to your guy at HR, seriously.
Just my 2 cents
Kindest regards, Marijn
@Fabien, I'm don't think template inheritance is essential. Why do you need to put things in a template that affect other templates? If you want a reusable template it better has as less ties as possible.
In general the one thing that bothers me the most about template engines is that the user pays the price for wanting to develop websites as fast as possible because the rendering of the template happens on user request.
You can cache a static content template but you can't for example cache a template with a form in it.
P.S. Very interesting read ;)
can you add some time measurements without compilation?
Thx
Thomas
FastTemplate!
PEAR states:
Always use <?php ?> to delimit PHP code, not the <? ?> shorthand. This is required for PEAR compliance and is also the most portable way to include PHP code on differing operating systems and setups.
It are these small things that enhance readability in group projects, or libraries.
Also:
It's a problem if you ever have to move your code to a server where it's not supported (and you can't enable it). Lots of shared hosts do support shorttags but "lots" isn't all of them. If you want to share your scripts, it's best to use the full syntax.
Could you provide a tarball with the code you used for testing ?
Thanks in advance
:)
@Flame On! >:]: We'd use a sandbox mode when producing a web app where advanced users can create their own templates for the system (some customers who know enough HTML to be dangerous like that feature, you know ;)). It's useful.
@david Template inheritance or blocks - I don't mind which way it's done, but so long as there's a syntax to add data from the child template to the parent then I'm satisfied. Inheritance is a very tidy way of doing this.
An example is a page which needs a JS library including in the page's <head>, for a visual effect. I don't believe that should be assigned from the controller, so I need some way for the page content template to inject the JS into the head.
- there is no intrusion of template code in a WYSIWG editor : my designer don't like to see {foreach} in is editor pushing his layout and breaking his alignments.
- the template code is bound to tags : the designer doesn't have to understand what he must cut/paste when moving his blocks ("hi, should I take the {if} part too ? oh and the other {/if}, ok.")
- you can have sample data in your template : for example you have a block "description" but if your template placeholder is {description} then you can't see the final look with a very long phrase, with PHPTAL you can insert your "lorem ipsum" in template, see what it looks like before being replaced with real data.
- i18n by a TranslationService : i'm using it to plug the I18N symfony plugin directly into the template, so, i just need to add "i18n:translate" attribute to a tag and it gets translated by sfI18N.
I can't wait to see PHPTAL as a common template system in future symfony relaeases.
Dont you see this template engine :
http://jelix.org/articles/fr/jtpl-standalone
regards.
Developers I know obsess over tidy, beautiful and minimal code everywhere but inside view files it seems. I like to write tidy, beautiful and minimal layouts but as soon as it must function it's like taking a giant dump in the file. Space wasting, format breaking php jargon everywhere! Ahhh!
I can use php and understand it but I'd much rather have an elegant solution that keeps the stuff I touch ever day organized and sensible. Why is this hard for many developers/programmers to understand?
Was that a rant? Shoot. Twig looks great!
In other words: What's with the Templating Component? Is it slower than/inferior to Twig?
I'm just curious because I never really used a templating engine in PHP and now I have the choice of two very well coded and, above all, very well documented ones! :) Where's the future of both heading?
Cheers and thanks! Daniel
As far as I understand what you mean by that feature, both Dwoo and Smarty have some kind of sandboxing through Dwoo_Security_Policy and Smarty::$security (and others). Those allow filtering of php within templates, and restrictions on the functions that can be called. If you are talking about HTML/JS filtering, I would rather rely on HTMLPurifier than any half-assed template engine implementation honestly.
Cheers
http://www.tinybutstrong.com/fr/
Its seems very intersting to me :)
I think a template engine is necessary ONLY in these situations:
1. 3rd party templates, or skins, is allowed, which can't be trusted(What if some skin creator wrote a small harmful piece of code in the template?). Then the "sand box" is needed.
2. the HTML coder need to work before the PHP coder. If there is no data or vars passed to template, how can these frontend coder to see whether their works are done right? But with a template engine, this can be done as below: (in smarty, left/right delimiters are "<!--{" and "}-->")
<code>
Hello
<!--{if $isUserLoggedOn}-->
<!--{$account}-->
<!--{else}-->
Guest
<!--{/if}-->
</code>
seriously, it is not that perfect, but "can" is better than "can't" right?
Except those 2 reason, i don't think I will use a template engine. Most of them are slow and odd ..
@fabien I am very impressive of you and your guys' work of symfony, Doctrine. Though I am not a big fan of template Engine, i still wish this Twig will rock the php world again.
Seems reasonably close to Twig, but no sandboxing.
I have always had an issue with php templating as my templates in most cases are not very readable.
With all the talk of templating lately and the release of the template component I have learned a lot of people are struggling with using php for templating - I have seen a number of great solutions (haml/phptal).
Twig looks very impressive - I definitely will try it out.
Also if you think about it, there's a lot of designers/front-end developers who already know PHP than those who know any templating engine.
And besides, it just add another layer of processing. PHP would be faster than a templating engine on top of PHP.
Anyhow, why should we assume designers are plain stupid? They're usually smart guys too...
It seems to me that templating engines are just reinventing the wheel, apart of the fact that you have to learn another syntax.
Also, there are a lot of inconsistencies in the reasoning here. Sure, having a subset of features will simplify the complexity of your templates, but from a developer point of view, you often want to use those missing features (eg. what's wrong with using array_chunk() or str_split() in a template), and webmasters are more likely to have notions of PHP than of yet another templating language to begin with. Secondly, the webmaster that is freaking out when encountering a PHP tag in his template, is likely to go completely insane on the sample code for template inheritance.
As a bonus, WYSIWYG editors are likely to recognize PHP syntax, and text editors are more likely to properly syntax-highlight it. Last but not least, the most efficient templating system is still native PHP, it's missing from your benchmarks.
Now don't get me wrong, I do see a proper use of Twig-alikes. Like you point out, when users need to edit templates on a backend, I do want the sandboxing. However, for all other uses, I specifically want to avoid being locked in a subset of features. I do hope Twig will not be built-in to tightly with Symfony 2, as personally, for the majority of my projects, I will not have much use for it, and I much prefer to have an easy way to disable it altogether in my projects.
:-)
I've since ditched the short tags, but for me, working in a solo environment, I'd rather have simplicity (don't have to learn a template engine syntax), control, and save the performance to spend later on things like actual application features.
Further, I'm not sure what all the heartburn over escaping variables in the template is about? IMO you should never be doing real work in the template anyway, any variables should be prepared in your controller class/script BEFORE being sent to the template. You're violating your own rule of separation of concerns by doing that much PHP work in the template. Likewise, making a function call in the template would violate the same principle. I've yet to encounter anything in two large scale enterprise apps that I couldn't template with PHP.
I also agree with the comments above that its not going to hurt the designer to learn a bit of PHP. Its really not that hard and it is a translatable skill. The en-vogue template engine of the day may or may not be in use in 5 years, but PHP will be.
I would argue that a very small percentage of total PHP developers are working in an environment where there is a separate templater that ONLY does the template work and has no knowledge of or role in application coding.
As for a few comments above:
- php short tag conflicts with XML.
- I think most designers can learn PHP if they have to, but, their time should be spend designing and not learning and programming PHP. I know a few designers that studied programming and still don't want to learn PHP. What concerns me is if designers will be able to easily get into the inheritance and other notions.
I worked some time ago with Smarty, and when compare to doing the same stuff with php, I totally go for the second one.
I think a template engine just could be needed when working with designers, even though they also could learn some php.
In the case when needing some sandboxing the template engine could be a must.
Twig seems really interesting and I wish it the best, but I don't think I'll use it in the near future in a project because most of the time I don't need sandboxing, or maybe I have to look closer in all the benefits it offers.
Jajajaj I still need plenty of time to look at all the projects you are on charge Fabien! Keep up the excellent work!
And btw, the need of escaping certain strings is inherent to all templating systems. Wether it's native PHP (w or w/o short tags), Smarty (oops, did I break my layout again with a block of JavaScript) or Twig for that matter.
I'm the "anonymous" user that voted down your uncon talk located at http://joind.in/959. I apologize for the anonymity, I forgot to login before I posted my rating/response.
Obviously I do not agree with your opinions on the importance of additional templating systems for php applications, but I am happy to see that you have at least done some serious research into the templating languages before making your decision to use them.
I guess my biggest beef with your rationale is that you can accomplish all of the things you mention without having to learn a new syntax nor any extra overhead from the templating language itself (even if it is fast like twig). As you pointed out, PHP doesn't have native tools to accomplish everything that you want (automatic character escaping), but that's not to say that such tools don't exist for the PHP community to utilize.
I do, however, wish I didn't vote your uncon synopsis so low. While I don't think templating languages are beneficial, I'm not really opposed to the discussion, and I think you are more than informed enough on the subject to lead a discussion about it. If your talk does go through, I might even stop by to discuss it in more detail.
Yes, a properly designed Model should already do all this... and we all know our Models are perfect, right?
...Eli White agrees with me re: escaping variables in your templates:
http://eliw.wordpress.com/2009/10/07/in-response-to-fabien-potencier-twig-php-templating/
(Fabien needs smileys on here so I can stick my tongue out like a 12 yr old :)
It has full Django style inheritence and a whole lot more.
It is always invalid to apply escaping in the controller, in the same way that gpc_add_slashes was a disaster. The problem is that the controller can't possibly be aware of the context of the output, nor understand which type of escaping is correct.
Consider:
<script>
<![CDATA[
var error_messages = <?php echo json_encode($translated_errors) ?>
function validate() {...
]]>
Your name is <?php echo h($fname + ' ' + $lname) ?>
<a href="foo.php?search=<?php echo h(url_encode($query)) ?>">search for <?php h($query) ?>
</script>
Notice how there are 3 different types of escaping that need to happen depending on the context (javascript, html, uris). It is impossible to know the context from the controller.
Also why are some developers so concerned about designers anyway? In my experience they don't touch the code. They create the overall site design and then code the html/css for the master template. A developer then installs the master template and takes over and does the page level coding. I wouldn't want a designer going into the code and going anywhere near programming logic of any kind. Designers design. Developers code. That's the separation of concern you should be adhering to.
Anyway, did you look at Open Power Template? I think that Twig does not offer the real power that an external templating language could offer, especially because it treats the static content as a plain text.
Good luck for the future development .
I wonder how you get time to maintain all these projects .
Anyway great work .
I kinda find the timing and tone of the "comparison" you've made here suspicious, though, in that you ask around for php templating engines on the 5th of october on twitter and you have a full fledged website for twig on the 7th? Doesn't seem like you're really that invested in looking for another solution as you seem to put on if you went all out like that in such a short time. *shrugs*
Jus' for a list of php (mixed in with other languages) templating engines that people might find useful for comparison.
http://www.invenzzia.org/en/download/about-svn
Yet, your features about object-orientation and sandboxing do open new fields to me.
Another issue with templating, apart from the syntax itself, is the physical integration of template files within a given framework. I have put together a little plugin that allows for total separation + template switching within symfony on http://objetweb.fr/blog/index.php?post/2009/10/06/Jouer-avec-les-templates-symfony. Any feedback appreciated.
http://www.codeassembly.com/What-cascading-html-template-sheet-is/
RE: Escaping vars in the template... If true John, then I would certainly not want to leave the decision of whether or not a var needs to be escaped up to the designer, who may or may not have any clue what the content of a given var is, whether it needs to be escaped or not, or even why escaping is necessary.
And that sort of invalidates the whole reason you'd want one of these easier-for-designers template engines anyway.
I agree with john above, I think most of the time the designer is going to hand the developer a static page/theme and it is the developer that will convert it into a template set.
Did you look at Flexy?
http://pear.php.net/package/HTML_Template_Flexy
Thanks.
http://www.tinybutstrong.com
@Skrol29 : TBS have a good approach, but is it optimized for PHP 5 ? Does it satisfies the needs expressed by Fabien ? Not sure.
I've found Zend_View + Zend_Layout to be the perfect tools.
-Escaping can be enabled automatically.
-Long verbose function calls can be placed in descriptively named view helpers.
-Short tags is always enabled because it's a great feature.
-Composition is used instead of inheritance making code more maintainable.
-No parser is necessary and helpers are loaded on demand which improves performance.
-New PHP developers will be more productive sooner using the native syntax.
-Good object orientated programmers will be more productive using an object orientated syntax.
PHP is a perfect template language. I've discovered this since working with Zend_View.
Template inheritance is a common design errors, when developers want to re-invent the wheel. I was very seduced by the idea when i started working with Django a year ago.
The experience shows that: inheritance is a design pattern that was not meant for views, decorators is a design pattern meant to manage views. Refer to GoF or any design pattern book if you want to make sure that this was proven *decades* ago.
Django template inheritance causes a lot of problems and does not offer an elegant solution at all when it comes to reusing templates.
What you want is an object oriented View class which is able to decide how to render a controller result for a request: which layout template and which templates to include with which context.
Read more about object oriented views:
http://ezcomponents.org/docs/tutorials/MvcTools#creating-the-views
Read more about template inheritance:
http://blog.chocolatpistache.com/blog/tag/template-inheritance/
$name_html = htmlentities($name);
$name_json = json_encode($name);
$name_url = htmlentities(url_encode($name));
$name_xml = xml_encode($name); //you have to write this one, alas....
I would never expect a front-end guy to actually understand the escaping requirements, since too many of them do NOT. For that matter, far too many PHP developers don't really get it.
Twig is actually slightly faster over the long haul (the benchmark ran a complete instantiate and render operation 10,000 times), so the different per rendering is down in the microsecond range. Just because I prefer PHP itself, does not mean I can't admire what Fabien (and the original developer) did with Twig. It really is as fast as is claimed. If you are going to make wild statements about Zend_View being really slow, you really should try it on someone who hasn't bothered to publish a benchmark that proves the opposite... Ignorance is bliss after all. Thanks for playing though.
The benchmark is at the end of this post: http://blog.astrumfutura.com/archives/420-Is-PHP-A-Worthy-Template-Language-Well,-of-course-it-is....html
Great article. I generally agree with your assessment of what a good template engine should do. I have been using Smarty as my templating engine for my phocoa php framework for quite a while. It's fine, but there are lots of annoying things about it.
I was going to try Smarty 3 soon but I think now I'll try twig. And thanks for offering the git mirror!
Alan
TBS has some assets described in this article.
TinyButStrong:
-Template oriented syntax: who can do best since it is the only template engine for whom templates can be edited with Dreamweaver and can be W3C compatible?
-Concision: very
-Automatic escaping: of course, an in several ways
-Object oriented architecture: yes
-Template inheritance: no. I don't share the idea to have object concept in the template side. Object concept is for developers. But TBS has sub-template features.
-Reusability: not in this way.
-Security: yes
-Sandbox mode: you can limit only PHP variable that are be automatically merged. All other limitations can be done in the PHP side anyway.
But I don't share all the points required by Fabien. And I would required other ones like:
- the engine can merge HTML as well as other textual contents
- templates can be edited by pro tools
- the template syntax is not another developer language
- the engine can be customizable (plugins, parameters)
- the engine is easy to use
Maybe I had been working with ZF too long :)
Nevertheless, they are optional "features". If you added the same to Twig it would be equally slow.
Issue of generating e-mails with PHPTAL is explained in the wiki:
http://phptal.org/wiki/doku.php/plaintext
Can you compare Twig with Blitz ( http://alexeyrybak.com/blitz/blitz_ru.html )
What can you say about this pic http://alexeyrybak.com/blitz/lebowski-bench-small.gif and where there placed Twig ?
require_once 'twig/Autoloader.php';
Twig_Autoloader::register();
$loader = new Twig_Loader_String('path_to_cache', false);
$twig = new Twig_Environment($loader);
$template = $twig->loadTemplate('Hello {{ name }}!');
$template->display(array('name' => 'Fabien'));
And Blitz:
$body = <<<BODY
hello, {{/$name}}!
BODY;
$Template = new Blitz();
$Template->load($body);
$Template->set(array('name' => 'Fabien'));
echo $Template->parse();