Templating engines in PHP - Follow-Up

Fabien Potencier

October 09, 2009

My post about template engines in PHP received more than 70 comments as of now, and counting. That's a lot considering most of them are really well thought out, and backed with solid counter-arguments. Thanks everybody for taking the time to participate constructively to the discussion. I'm really proud that the PHP community (or at least the small part which reads my blog) is able to discuss such a touchy topic without immediately starting a flame war! I'm also impressed about how many people need to promote their own template engines ;)

Before I try to answer some questions, I'd like to reinstate that I like PHP templates. And you should remember that symfony has only used plain old PHP templates since the beginning. As a matter of fact, I'm been advocating about using PHP templates since my first PHP project, and I have never used any other PHP template engines. So, I'm not against PHP templates; I just find that some PHP limitations as a template language are more and more irritating for me.

And as Eli has pointed out, "[I probably have] grossly undersold PHP-as-template in [my] enthusiasm to promote [my] new templating language that [I] created".

I also like Tchalvak comment: "The question of PHP vs a templating engine isn't the essential one, the essential (and easily answerable one) is templates vs. no templates. Templates - and the separation of display vs. application logic that they bring with them - are a necessity. What form they come in is much less important.". He sums up really well the question. More on that later on.

I understand all the points raised in the comments, and I basically agree with most of them. Now, let me answer some of the more interesting questions.

Twig Background

I started to look for a template engine a few months ago. People who know me also know that I don't like to reinvent the wheel. So, I didn't want to create a new library from scratch.

I looked for a good template engines, I tried some of them, and finally found Twig. But as soon as I started to use it, I found that it was exactly what the gem I was looking for (because of the features it already had and also because of its clean and beautiful architecture). As Twig was not a standalone project, but rather an embedded project, I started to hack it a bit, and after I made several enhancements like the sandboxing feature, I decided to contact Armin to discuss the future of Twig.

So, you are not sold... yet?

Even if you don't buy my arguments, that's fine. I don't want Twig to become the universal template language for PHP, far from it. I really think there is a market for template engines like Twig, but I'm the first to recognize that it won't be used for all PHP projects to come!

If you are looking for a templating engine that only uses PHP and have built-in support for template inheritance, blocks, helpers, and some more, the good news is that I have coded one some weeks ago under the Symfony Templating Component name. It's a standalone component, which has no other dependencies, and I'm sure most people wanting to use plain PHP for their projects will love this project.

And better yet, you can use both Twig and the Symfony Templating component to have the best of both worlds. Use the component for all your templates and Twig if you need the sandboxing feature.

About the Syntax

Lots of comments about the syntax, and the problem I raised about the PHP syntax. It's not about having a prettier syntax and if you think that the syntax issues I mentioned are mostly bikeshed color arguments, think again.

One of the key point of my reasoning is that a good template language should aim to find the sweet spot. The template language should find the best compromise about too many and not enough features. As I said in my previous post, the template language is all about presentation logic. And of course, simple conditions and loops are part of the presentation logic. But do you want to use array_chunk() in a template? Probably not. This call belongs to the controller or the model, depending on what you want to do.

Also, templates are about a lot of HTML with some PHP. So, this kind of code snippet is a big no-no for me in a template:

<?php
    if ($items) {
        foreach ($items as $item) {
            echo "* {$item}\n";
        }
    } else {
        echo "No item has been found.\n";
    }
?>
 

Many people seem to like the PHP short tags. First, about the math. If you compare <?= $var ?> with <?php echo $var ?>, the difference is 7 characters, not 2. But that's really not the main problem.

Apart from problems like XML support, the short_open_tag setting, the shared hosts configuration issue, and some more, it's also about coding standards:

  • PEAR:

    "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."

  • Zend:

    "Short tags are never allowed."

The Pear and Zend projects are serious, so there should have some reasons to disallow short tags, no?

But as Eli mentioned in his post, I would also like to see a PHP evolution to take this problem into account: "... there are a number of people (including myself [Eli]), 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 <? ?>"

About Web Designers

The debate is not about if web designers should understand PHP or not. And it's certainly not about web designers not being smart enough. Of course web designers can learn a bit of PHP... until they learn too much and start getting stuff that do not belong to the template in their templates (like getting records directly from the database, anyone?) Oh, of course, they won't do such a mistake it they have also learned about the MVC pattern. But then, they are not web designers anymore, they are web developers.

Finding this good balance is all about providing a tool that tries to help web designers not to shoot themselves in the foot. And I think everybody will be with me if I say that PHP does a poor job setting the limits.

Output Escaping

Some commenters advocate that output escaping should be done in the controllers. That cannot work. As John Campbell writes: "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."

The issue is therefore not that simple. On the one hand, developers should take care of output escaping, but it cannot be done in controllers. On the other hand, web designers should not have to take care about output escaping, but templates is the only place where you have enough context information to apply sensible escaping. That's why automatic output escaping seems the best compromise to me, plus the fact that being "almost" secure by default is a big advantage.

Speaking of automatic escaping, I'm probably someone who knows a lot about it as symfony has this feature since early 2006. I can tell you that the performance overhead of such a feature is very high. In Twig, it is added during compilation, so there is no overhead whatsoever.

About Sandboxing

The sandbox feature is not targeted at web designers. It is mainly useful for situation where external people can change the templates (think of webmasters able to configure their CMS or blogging platform templates from a backend interface).

The Dwoo and Smarty security feature is a right step in that direction, but not as powerful as a full sandbox feature. As far as I understand, it's mainly about allowing PHP code or not in the templates, and restricting the PHP functions you can use (of course, correct me if I'm wrong).

Sandboxing controls everything, from the tags you can use, to the methods you can call on the objects (the Twig documentation explains the concept and how it works).

About Speed

Most template engines compile the templates down to PHP code. So, the speed of lexing, parsing, and compiling is not that relevant. What matters is the speed of the evaluation. Here is the compiled version of the Hello {{ name }} template:

/* Hello {{ name }} */
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Twig_Template
{
  public function display($context)
  {
    $this->env->initRuntime();
 
    // line 1
    echo "Hello ";
    echo (isset($context['name']) ? $context['name'] : null);
  }
}
 

Some people were worried about debugging. As you can see, the generated code is very lean, and contains the template name and the lines of the original template. That should be more than enough to debug all the possible problems easily.

You can find it much more verbose than the PHP version, and of course, for such a contrived example, the native PHP version is insanely simpler:

Hello <?php echo $name ?>
 

But have a look at the generated code for many template engines and you will see for yourself that Twig output is one of the cleanest and shortest one.

As asked by many people, I have redone my benchmark by bypassing the compilation phase altogether (the cache has been primed before launching the benchmark scripts). As I expected, it does not change numbers significantly. The compilation of such simple templates is insignificant compared to the rendering of 10,000 compiled templates.

I have also tested plain PHP templates. So, here is the updated table:

Library Time (sec) Memory (Kb)
Plain PHP 2.4 114
Twig 3 383
PHPTAL 3.8 598
Dwoo 6.9 1,645
Smarty 2 12.9 610*
Smarty 3 14.9 799*
Calypso 34.3 614
eZ Templates 53 2,783
  • Notice that the memory used by Smarty is much lower than the memory used in my previous benchmark as I wrapped the whole loop with an ob_start()/ob_end_clean(), which was not fair comparing to the other template engines. This was fixed in this new benchmark.

So, as expected, PHP is faster than Twig for simple templates. But as templates become more complex, the difference will be less and less noticeable, due to the clean code generated by Twig.

The benchmark scripts are executed on the command line without any PHP accelerator. A PHP accelerator in this case does not help as everything is done in one single PHP process.

You can download the benchmark code here: http://fabien.potencier.org/benchmarks.tgz

Twig and Symfony

This section is for people worried about the integration of Twig as the default template engine in symfony.

symfony 1.3/1.4

Obvisouly, Twig won't be part of symfony 1.3 as the feature-freeze deadline is the end of next week and also because we want the symfony 1.3 release to be an evolution of symfony 1.2, and not a revolution.

If some people want to create a Twig plugin for symfony 1.3, start the discussion on the symfony developer mailing-list, and I will help you getting started.

Symfony 2.0

As far as Symfony 2 is concerned, nothing is definitive yet, but Twig won't be the default template language. I think Twig will be available as an optional plugin, well integrated with the core. For instance, it will probably make sense to use it for the admin generator to provide some specific tags that will ease the customization of it.

And thanks to the Symfony Templating Component, developers will be able to mix PHP templates and Twig templates easily in one project, depending on their needs or the tools they want to use.

So, if you can't stand template engines, use plain PHP templates; but if you want to benefit from Twig, use it natively. And of course, if you use plugins that made the opposite choice, that won't be a problem either.

Conclusion

Hopefully, this new post has answered some of the points raised in the comments.

Discussion

gravatar @futurecat  — October 09, 2009 15:41   #1
There's a lot going on since you released twig. We can see a lot of developer giving their 2cents on what a designer should or shouldn't be allowed to write in a template file BUT no designers took the chance to comment your post. I guess they don't read php blogs ;-)

It would be really helpful to know which templating system they like/hate and why they like/hate it, which feature they'd like, etc etc...
gravatar umpirsky  — October 09, 2009 15:48   #2
Zend and short tags - http://framework.zend.com/manual/en/zend.view.html#zend.view.introduction.shortTags
gravatar Mr. Jérémy ROMEY  — October 09, 2009 15:50   #3
Yes this post did answered the points raised in the comments !

I think the "template VS no template" will be open for a long time... It's not over...

The force of PHP is you can use what you want, so I hope we will have the choice to use it in Symfony.

jeremyFreeAgent
gravatar Hari K T  — October 09, 2009 16:36   #4
Hi ,
I have added Twig to the wikipedia . I don't know whether the things I have added is correct or not as I have not used any before.

http://en.wikipedia.org/wiki/Template_engine_%28web%29#Comparison

Please edit it , if anything went wrong.

Thanks
gravatar Jonathan Bond-Caron  — October 09, 2009 16:51   #5
Where's the benchmark code for the other template engines?

It's a pretty shameless way to promote the template en gine *you wrote* with *one benchmark* and not provide the code.

Other then that I'm happy to hear about Twig, smarty could use a performance boost.

You can easily remove/disable some smarty features and make it a lot faster while keeping the same synthax.

gravatar Fabien  — October 09, 2009 17:04   #6
@Jonathan: I said I will publish the code of the benchmark and I totally forgot to do so. Sorry about that. The code is now available here:

http://fabien.potencier.org/benchmarks.tgz
gravatar Gerry Vandermaesen  — October 09, 2009 17:31   #7
"The Pear and Zend projects are serious, so there should have some reasons to disallow short tags, no?"

Yes, but I'm willing to bet you're perfectly aware you're quoting coding standards for scripts/extensions meant for distribution :-) Apples and oranges!

I'm glad you quote the array_chunk() example. Do you want to use that in a template? Indeed, probably not. But in some cases it might still make more sense to do inside the view, instead of in the model or controller. Do I really want to create a plugin for a templating system for the oddball template that requires splitting my list in chunks for multi-column display?
gravatar Pablo Godel  — October 09, 2009 17:55   #8
I asked a web designer friend with many years of experience and some PHP knowledge and he prefered the Twig syntax rather than PHP. I will continue to ask around to get a better perspective.
gravatar Pepito Grillo  — October 09, 2009 18:21   #9
Sorry but... escaping shouldn't be done in the model? If I'm not wrong (unless you're using a fat controller, of course), the model is the one who really knows which data and for which reason is being pulled from the DB or any other sources. So, obviously, it knows what needs scaping, doesn't he?

If you need to escape stuff in the template, then something is not properly done. Remember that the model and the template are supposed to be fully coordinated...
gravatar Arie Karhendana  — October 09, 2009 18:54   #10
@Pepito: You're referring to DB / SQL parameter escaping (which should be done in the model to avoid SQL injection), while in the post Fabien wrote about output escaping (e.g. htmlentities() function).

Output escaping should be done at the view level, because only view knows what kind of escaping should be done depending on the context (HTML output, RSS feed, etc.).
gravatar Tchalvak  — October 09, 2009 19:15   #11
I think the benchmarking is great, and shows a good faith in this situation. Your earlier post kinda struck as being a little bit straw-man argument-y (in a large part because the profusion of template engines makes it hard to accept that there are any niches left, hard to accept that there's a sweet spot that hasn't been hit), but I think that the benchmarking pretty much squashes that. I expect you're trying to be fair and all as much as you can, the topic just happens to be one that puts people up in arms, it's like vi vs. emacs but with 50 opposing sides. Which makes me wonder why you want to bother getting into the template thing in general. *smiles*

Escaping by default and a non-horrible looping syntax may make me leave smarty and go for Twig instead, despite smarty and Twig both being overkill for the dead simplicity that I'm using in templates.

Anyway, you've convinced me to look into Twig, despite that it is far beyond what I need, but I'll probably get in on the developer mailing list a little.
gravatar Matthew Weier O'Phinney  — October 09, 2009 19:48   #12
@umpirsky Thanks for the reminder that I need to update that section of the manual (regarding Zend_View). We have not recommended short tags for several versions now, as the compatibility argument is compelling. While we still offer the stream wrapper, the warning following that section still applies: it degrades performance. It's best to simply use long tags everywhere.
gravatar Tchalvak  — October 09, 2009 20:47   #13
Twig benchmark throws a notice, which may make comparison hard, as does the lack of units.

tchalvak:~/ninjawars/benchmarks$ php bench_twig.php
FOO
Hello Fabien&lt;br /&gt;
Notice: Undefined variable: context in /home/tchalvak/ninjawars/benchmarks/templates/twig/cache/twig_08029d630b7a1a1b22e72a7ec39cea56.cache on line 15
Call Stack:
0.0013 117488 1. {main}() /home/tchalvak/ninjawars/benchmarks/bench_twig.php:0
0.0367 1751776 2. Twig_Template->render() /home/tchalvak/ninjawars/benchmarks/bench_twig.php:14
0.0367 1792792 3. __TwigTemplate_d8fb9d03f55738ff78518e1bc2741faf->display() /home/tchalvak/ninjawars/benchmarks/lib/twig/lib/Twig/Template.php:27
0.0383 1914416 4. __TwigTemplate_7521903ccfecfc128068db78c2a8bf4c->block_content() /home/tchalvak/ninjawars/benchmarks/templates/twig/cache/twig_d8fb9d03f55738ff78518e1bc2741faf.cache:12
0.0482 2117488 5. __TwigTemplate_08029d630b7a1a1b22e72a7ec39cea56->display() /home/tchalvak/ninjawars/benchmarks/templates/twig/cache/twig_7521903ccfecfc128068db78c2a8bf4c.cache:13

* First
* Middle
* Last
BAR
2,159,728
--And Again (with notice)--
BAR
669,936
--And Again (with notice)--
BAR
669,936
tchalvak:~/ninjawars/benchmarks$ php bench_smarty.php
BAR2,309,856
tchalvak:~/ninjawars/benchmarks$ php bench_dwoo.php
3,110,632
tchalvak:~/ninjawars/benchmarks$ php bench_php.php
308,904
tchalvak:~/ninjawars/benchmarks$ php bench_smarty3.php
4,429,984
tchalvak:~/ninjawars/benchmarks$ php bench_phptal.php
3,731,784
tchalvak:~/ninjawars/benchmarks$ php bench_ez.php
INFINITE LOOPS AND HAS TO BE KILLED
gravatar Philippe Gamache  — October 09, 2009 21:53   #14
I think this is great... Many time, designer and integrator are not very good with PHP and others programming languages. In fact, many of them don't what to have to learn them, specially when they work with different teams. I was working for a client that have team working on symfony project, drupal, .net, java, pythons, ect... So I had to integrate myself all the HTML into our symfony template...

Not as fun.
gravatar Fabien  — October 09, 2009 22:38   #15
@Tchalvak: Can you send me the files in the /home/tchalvak/ninjawars/benchmarks/templates/twig/cache/ directory? fabien.potencier [at] symfony-project.org. Thank you.
gravatar BenLeTibétain  — October 10, 2009 01:11   #16
@futurecat ++
gravatar Jonathan Collins  — October 10, 2009 02:52   #17
Looks like the PHP tags in the quote from the PEAR docs are not properly entitized.
gravatar Vincent Dieltiens  — October 10, 2009 15:25   #18
Hello :)

My point of view is that the question "template VS no template" is really over : Yes a template is essential. And it's the goal of the view.

The real interresting questions are (for me) :
- What needs a template, what it can do ? (which "instructions" ?)
- What can't do a template ? (for instance, accessing the model)
- Where we can we put some "tentendious" things like output escaping ?

When those questions are answered, i think that we can imagine a powerful template engine.
But... it's not easy to answer those questions...

Why people want necessarily put output escaping either in the template, either in the logic part ? why not in a fourth component "Renderer" ? So no more MVC but MVCR (or MVRC) ? because for me, that is the more logic solution.

I've write a report for a project in first Master at university (2 years ago, in french (i'm belgian)) but i can't post it now because i'm not at home :).
I will try to give a link monday or tuesday.

I'm very interrested to this topic and opened to discuss about :)
gravatar Vincent Dieltiens  — October 10, 2009 15:27   #19
Sorry for the mistake : I've written* ;-)
I'm not so good in english ;-)
gravatar Pádraic Brady  — October 10, 2009 16:18   #20
Just on one point - you can access a Model from the View (if you actually refering to Model-View-Controller). It's one of the essential parts of MVC to prevent the pollution of the Controller with unnecessary tasks.
gravatar Jory Geerts  — October 10, 2009 17:18   #21
The way I see it, the template/templating engine isn't the view. Its a part of the view, but there are other parts. And one of those other parts does things like output escaping. So no auto-escaping in the templating engine for me, please. :) (If I'm reading the documentation right, if you don't use the 'Escaper' extension, Twig won't auto-escape, right?)

Twig looks pretty nice. The syntax for the designer is pretty easy, with plenty options. I think I'll poke the designer of a project I'm working on to see if he likes it as well.

I do have one request, can you make the date filter locale aware, or add a locale aware date filter? (Locale aware dates in PHP can be done with http://php.net/strftime) Locale awareness, in my opinion, is pretty important for a templating engine.
gravatar mohrt  — October 10, 2009 17:22   #22
A post about this thread is now in the Smarty forums.

http://www.smarty.net/forums/viewtopic.php?p=60071

Also see my topic on PHP as a template language:

http://www.smarty.net/forums/viewtopic.php?t=15286
gravatar Vincent Dieltiens  — October 10, 2009 17:37   #23
@Pádraic Brady Accessing the mode is precisely against MVC. Ok Model must contains a maximum of things and controllers must be small. But precisely the controller is between the model and the view. The goal of the controller is to get informations from user (parameters and so on), retrieve informations from the model and give to the template what the template needs.

If template accesses to the model, it is dependant of this model, you can't use it with an other model...
Imagine a "sub-template" that is listing a set of elements.If you don't get the list directly from the template by accessing the model, you can reuse it for a list of an other model .
gravatar Don  — October 10, 2009 22:31   #24
Boring, boring...
Every few weeks a new discussion about template engines. Instead of dicussing good architectural software design.

As some stated, to have a template (engine) is ok.
But the V in MVC is more then the template.

A template should get the information it should get and display. No more and no less.
No more means ONLY that information.
No less means ALL stuff like formatting and escaping already done.

Saying "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."
is simply bullshit.
Why that should not be possible?

It's simply PLAIN wrong to do escaping in templates. Then you could continue formatting, regular expressions and so on. So where's the separation between a developer's and designer's concerns?
How could I give templates to designers, do they have to learn how to escape the various variables and content? You're kidding.

It's quite simple to do the required escaping BEFORE output. If it's not then you know that there's something wrong in your architecture.

I know the context, I know who is requesting my content and I know why. So where's the problem?

Here it is: it's not in discussions like this one but in the heads of lazy developers who are not willing to learn how to properly layer and separate information, code, commands, queries and concerns.

gravatar Tchalvak  — October 11, 2009 00:46   #25
Case directory sent.
gravatar Richard Lynch  — October 11, 2009 06:05   #26
I think the controller SHOULD know where the output is going, and thus be able to properly escape it...

As far as templating engines go, if I'm forced to use one, at least give me the PHP extension Blitz so it's fast.
gravatar Pádraic Brady  — October 11, 2009 13:44   #27
@Vincent Dieltiens You are completely wrong. Sorry, but every single UML diagram of MVC will show the association between the View and the Model.

The View is ALWAYS dependent on the Model - where do you think the data comes from that the View displays? Passing it through the Controller does nothing to remove the dependency on that data, and may in fact lead to an overarchitected poorly performant design (something Zend Framework people realised...eventually).

Views SHOULD access Models where the access is read-only and the code for the access capable of being abstracted behind a simpler API, i.e. a View Helper or a tag-based addition when using a tag language like with Twig.

@Richard Lynch The only part of MVC responsible for output escaping is the View. You can perform it openly in the templates, or use some simple interception (e.g. __get() in PHP) and a set of rules to determine what to escape, to escape values automatically as they are accessed. Twig does this by compiling in the escape calls, PHP native can use interception in the object housing the View related variables. Doing it from the controller only shifts the problem somewhere else, though it does have the advantage of removing the escaping duty from the template editor. It's problem is the Model-View interaction - Model access does NOT have to pass through the Controller, so the Controller never has 100% control over what data enters the View.
gravatar Pepito Grillo  — October 11, 2009 16:16   #28
To Arie Karhendana and Pádraic: Excuse me both, but I still think (and I completely agree here with Richard Lynch) that all ESCAPING has to be done in the model: If model and view are to be tightly integrated, then the model needs to properly escape for whatever output media the data is intended for, say HTML, RSS or even as a provided service.

Furthermore, the controller also needs to be aware of the type of output media the data is intended for, so he "orchestrates" everything OK. Apples for apples and pears for pears. If we serve apples instead of pears when pears were expected, then the application design is wrong...

But this is my humble opinion and I can also be wrong...

By the way, the model is also responsible of all validation required, either to avoid SQL injection, either to avoid any other type of forgeries.
gravatar DrSlump  — October 11, 2009 17:31   #29
In essence I agree with Pádraic, output should be escaped in the view "layer", which does not correlate directly to a template!

The problem, as I see it, is that we are told to follow MVC initials very strictly, while in reality the Model is composed of several components (validation, business logic, persistence and view model). The validation part ends up tightly coupled with the Controller while the View model is coupled with the View. It's impossible to have a fully de-coupled architecture, it would be like building a car chassis without axis for the wheels. We need some "glue" components in there to make it work together.

So, while a template shouldn't know how to escape data, it just needs to know where to output it, the view model must be responsible for the escaping, which in a "template engine" maps to the template "context" and its helpers.

To summarize, in a fictional template syntax, it would look like this:

{html: $VarWithHtmlInIt}
{js: $VarWithJsCodeInIt}
{text: $VarWichIsEscapedToShowAsText}

Then it's up to the view model (via helpers or the template engine context/runtime) to supply the appropriate implementations for the html, js and text helpers (basically encoding and replacing especial chars).
gravatar Pádraic Brady  — October 11, 2009 23:52   #30
The obvious problem with escaping for a View within a Model. The Model knows exactly nothing about the View. Why should it?

The Model is a representation of state, and the domain logic which acts upon that state. Whether an external actor wants to stick that state into HTML, XML, JSON, CSV, PHP, or any other format is its business. Therefore, only such an external actor actually knows the correct means of escaping the data it received from the Model, whether it is a Controller, or the View itself.

Unless, of course, you make the Model aware of the View. In which case, congratulations, you just broke one of the primary separations contained in MVC (check a UML diagram - the little arrow in the line connecting the View to the Model is a one way association).

Developers should note that "automatic escaping" within Views has been around for a long long time as a form of Poka-Yoke safe guarding. It's about time PHP developers figured that out. Kudos to Fabien, it's been part of Symfony for a long time now. I don't completely buy the performance problems (I use it here custom implemented into Zend_View with no measureable performance hit), so nobody should be afraid to look into the implementation possibilities.
gravatar umpirsky  — October 12, 2009 10:08   #31
One question:

Why {{ var }} and not {var}?
gravatar drako  — October 12, 2009 13:19   #32
I'd been working with Smarty before and won't do it again. I think that its basic flaws apply to other template engines as well. Basically everything is ok, when you have simple views. But when things become more complex, when you need to use lots of loops and conditions suddenly you get one big mess and often one have to use hacks to achieve the needed effect. Plus everything is written in other language than PHP plus there's often no syntax highlighting and we get something very unreadable.

One thing that wasn't mentioned - templating engine requires its syntax knowledge not only from designer but from developer as well. It's an additional work for developer to pass data to template in the way the templating engine will understand. Developer should focus on coding not thinking how to pass things to template.

The point about designer accessing model from views is very easy to avoid - pass arrays to view. Propel has the "magic" method toArray() which I found very useful.

As to where the escaping should be done - my guess is controller. Controller knows what view will be called and what escaping is needed. That way model remains separated from the view and even if we switch to different model data will remain escaped.
gravatar Don  — October 13, 2009 16:34   #33
Always funny who (PHP) people start to throw with terminologies they don't really understand.

MVC should never have happened.
It led us to Sodom & Gomorrha.

First understand that the M is almost ever just the Model of the frontend (application). In most cases these are stupid DTOs that came from a read-only layer.

M is not the domain model (or call it business logic).

The lakmus test for clean separation is:
Imagine you app layered for providing an external API, e.g. eBay API.
What features you would give the users of your API, what they could do with your data and business logic?
Allow every formatting or escaping you don't need, but do all that stuff youself when it comes from that sources, don't trust anyone.

I could do anything in my model with my frontend MVC app above it. But I cannot do anything below it that is "business logic".
So it is pure UI.

Btw: every data I show in the UI there is stale.
It is only fresh for a fraction of time. I cannot do any assumptions on the data I get from a datasource or see on the screen.
If I auth and load an user from the domain model (backend/API) he could be deleted 1/1000s after that.

Therefore my UI, e.g. made with MVC, MUST be dumb.
gravatar Chris Renner  — October 13, 2009 16:46   #34
I just want to say, after following this whole drama for the past week, that this is exactly the kind of discussion we should be having in the PHP community.

Fabien, I don't agree with you on many of your points, but just wanted to say thanks for creating such a lively debate.

Regardless of where you come down on this issue, I think these are important questions every developer should consider.
gravatar Zyx  — October 18, 2009 13:04   #35
Fabien, I think that your benchmark is based on invalid assumptions. You render a template 10000 times, which contains an "include" statement. This would be good, if you provided the execution of each "rendering" in a separate process. Now it only shows that 10000 inclusions are faster in template engines that compile templates to classes which need to be loaded once, than template engines that produce plain PHP files loaded every time. But this is OBVIOUS. I personally cannot imagine a website that includes the same thing 10000 times per request, where such buffering could be useful, but I can imagine a website that performs a couple (about 5 - 10) includes, **for different templates each**. So you should either provide a process isolation to provide a more reliable results, remove include from the test or remove the 10000-times loop.
gravatar Jens-André Koch  — October 23, 2009 04:28   #36
Let me add two things:
a) Using templates means to add a layer of security. When it comes down to argumentation, this is the critical point. It means to restrict the number of available php commands to a certain number.

Let me turn this into a question: What's the best way to restrict the command set with the current PHP?
One solution is to build a lexer and a parser for a template syntax (basically that's what Smarty is and will be). But is there another way to limit the php command set directly?

b) Using templates means also to hide the work done on the data for the placeholders.
All transformations (escaping, cutting, stripping, preparing, etc.) of outputdata should be done (a) before assigning the data to the view (push) or (b) directly when fetching from the view object to template (pull). And I really like the idea of the two-step-view pattern, where the first transformation is done on the model data turning it into a logical presentation without formatting and the second transformation applying the actual formatting.
gravatar Sylvain_G  — October 29, 2009 22:00   #37
Nice stuff, it give it a very basic try and notice that produced php code include <?php but no closing tag. Any reason for such a oddness?
gravatar zvince  — November 01, 2009 00:44   #38
I would like to adress many thanks to Don, who brought the light into this post.

"MVC should never have happened." Well, why not ?
"It led us to Sodom & Gomorrha" If my mother happens to know that I use MVC, she will kill me ! and send me to hell ...
"stupid DTOs" If you find stupid things in this job, you might better do another job ...
"Btw: every data I show in the UI there is stale." Do you mean that data retreived by the model gets deprecated while being transmitted to the view ? You might change your computer. Today we can find good performance at affordable price. But maybe you like your grandfather's computer better ...
I will not comment the entire post, no need for that ...
gravatar neothemachine  — November 17, 2009 17:17   #39
I just came by these blog posts today and would like to give my 2 cents.

Sometimes I think people are missing the bigger picture of all this. What are templates good for? Making life easier for web designers? Added security? Maybe.

I have been using PHP for many years now and from studying I also have a good background in Java. Of course, you can't compare websites with desktop applications but they share things. Think about doing a GUI in Java's Swing (although it's pretty much crap :P). You could possibly just code in pure Java or invent/use a template engine. Both approaches have their right to exist, but the big point is: When should each be used?
Just take Firefox, there are addons and I think all the layout stuff is pretty restricted by its template engine by using html, js or whatever. Why? Because it has to! Nobody knows what addon developers will do in their addons, so they need the added security.
On the other side, if your html never leaves your website/company and nobody from outside can alter it, then why use template engines? You don't have added security because you or your developers are writing the (secure) code. And yes, I think web designers should also know basic php. Of course, they could do the baddest unsecure things by using php directly, but is it the best way to just put them in a crippled environment with limited possibilities? I think the better approach is just to do regular code reviews! You or someone else would immediately see strange code which should obviously not belong to the view layer.
Even if code leaves the company, like plugins in symfony, would you want these all to be written using a template language? It's open source, everybody can see it's code, so WE are the code reviewers whereas in Firefox this is probably not possible because most addons are not open source (correct me if I'm wrong).

So, long story short, I think the work of Fabien, and its newest addition Swig, is excellent. But you have to make yourself clear when you really need a templating engine. In the past I used them only for one spot in my website, and that was an internal form where staff could create the newsletter. I used Smarty for that but really missed the feature of checking the validity of the code, so I WILL use Swig, but not for website layouts. There are just too many downsides of it, despite the few good sides. And if it's just autocompletion, syntax highlighting (which could maybe be accomplished by plugins for your IDE) or speed. I also agree with the others saying that php didn't evolve as a templating language which is a shame but to me using a template engine in all your view layer code is just a way too big workaround.

I would love to hear your opinions on this!
gravatar cindy  — November 27, 2009 03:15   #40
Hi Fabien, I 'am a green hand in PHP, I have to finish a project with the TWIG, I had read many document and the Twig-project website, but Still now I don't understand how to use the Twig very well , can you help me or send a simple example, thank you very much!