What would make template engines actually useful?

January 19, 2009 – 9:42 am Tags:

Probably all of us have used template engines in one form or another. Some might even like template engines for whatever reason, but let’s think about it for a moment: are they actually making our lives easier?

Most template engines simply wrap PHP (or some other language’s) syntax into their own syntax, and maybe they look a little bit cleaner when mixed with HTML. Some may even provide useful features like automatic variable escaping to prevent XSS vulnerabilities.

But does this actually significantly reduce the amount of code needed to write some common scenarios, or make it easier to read/manage the code?

Case 1: tables

Tables are an excellent example of what I mean. Sometimes you may want to display a table’s first row with a different style than others, or maybe you want to display every second row with a different style?

The typical way to achieve this is to create a variable in your template and compare against it in the loop:

<?php $first = true; ?>
<table>
 <?php foreach($rows as $row): ?>
  <?php if($first): ?>
   <tr class="firstrow">
   <?php $first = false; ?>
  <?php else: ?>
   <tr>
  <?php endif; ?>
 
  <td><?php echo $row[0]; ?></td>  
  <td><?php echo $row[1]; ?></td>
  </tr>
 <?php endforeach; ?>
</table>

So there’s some extra cruft, but it’s not so bad. Consider the following in Smarty, which does about the same:

<table>
 {foreach from=$rows item=row name=loop}
  {if $smarty.foreach.loop.index == 0}
   <tr class="firstrow">
  {else}
   <tr>
  {/if}
 
  <td>{$i[0]}</td>
  <td>{$i[0]}</td>
  </tr>
 {/foreach}
</table>

Pretty much the same. Only big difference is that you didn’t need to declare the variable yourself.

Couldn’t this be done with some less code? Or maybe with some more HTML-like and simpler to read code? Here’s how it could look:

<table tpl:var="rows">
 <tr class="firstrow" tpl:type="first">
  <td>1st</td>
  <td>2nd</td>
 </tr>
 
 <tr>
  <td>3rd</td>
  <td>4th</td>
 </tr>
</table>

Here, the template engine could loop through rows, and display the tr with the type attribute only as the first row, and use the other tr for the rest of the rows. It would also automatically fill the td’s using the indexes from the array.

I think the last snippet is better than the PHP and Smarty versions. You may notice some similarities to PHPTAL, but the example is much less verbose than PHPTAL’s templates. It could even be condensed some more: we could omit the td elements inside the first tr – the engine could just guess that you want to use the same tds as in normal rows, which is a reasonable assumption. You could, of course, always provide the html inside the first tr as shown in the example.

Using this kind of template markup, you need to write less code to achieve the same result. Not only that, but the markup is cleaner because you don’t have PHP mixed in with HTML, so the code becomes easier to read and modify in the future.

Case 2: filtering

This is another common scenario: You’ll want to filter your variables so that users can’t insert arbitary HTML snippets or other malicious code.

Typical PHP code for it would be something like this:

<div>
 <h1><?php echo htmlentities($title); ?></h1>
 
 <p><?php echo htmlentities($content); ?></p>
</div>

And typical Smarty example:

<div>
 <h1>{$title|escape}</h1>
 
 <p>{$content|escape}</p>
</div>

You could say the Smarty example is a bit better as it requires less typing, but you’re still repeating the escaping.

How about this:

<div tpl:filter="htmlentities">
 <h1 tpl:var="title">example title</h1>
 
 <p tpl:var="content">example content</p>
</div>

We declare a filter attribute on the div, and then use a var attribute for the child elements. The var attribute would replace the example content in the nodes, and it would “inherit” the filter behavior from the parent div element and use htmlentities to escape the variables. No repeating for filter, and if you add some new tpl:var calls inside the div, you won’t need to remember to add the filtering code to it like you would have to if you were using pure PHP or Smarty.

The engine could also support automatic filtering. In that case, you could disable filtering, or change to a different filter function, by using the filter attribute.

More on different attributes

Of course, just having these few features wouldn’t make the engine really useful. You could extend the idea to providing an easier way to write forms, or outputting values from a class instance.

For example, when writing a form, you often have to output error messages or other such things. A good template engine should allow you to define this without having to resort to using lots of if-elses or other tricks.

Outputting values from class instances could also be made a bit simpler. For example, you often have a specific element inside of which you output specific values from an object. For example, a user details box on their profile. We could have the engine do something like this:

<div tpl:var="user">
 <h1 tpl:method="getName">User's name</h1>
 <p>Registered: <span tpl:method="getRegistrationDate">YYYY-MM-DD</span></p>
</div>

The above could even be expanded a bit further: In the span element for the registration date, we could have the template engine read the date format from the span, so that it gets formatted into the format inside the element.

You could also use tpl:method for calling any object’s methods, if the object was provided to the template. For example, tpl:method=”myObject.someFunction” could call $myObject->someFunction() in context of the template.

It should also allow you to write PHP in the templates if you wanted. You can’t expect that the template language is enough for everyone, and there is no real reason to not allow PHP in the templates as the idea is to make it easier for the programmer.

Conclusion

If a template engine did let met deal with typical cases like these using less code and by making it simpler to understand the code, I think I would use it.

In addition to that, it should let me use PHP in the templates if I wanted. Sometimes you just need to use PHP for more flexibility. It should also be easy to extend, so that you can write custom attributes or maybe even tags.

I’ve actually implemented a basic template engine, which supports var and filter attributes. There are, however, some challenges in implementing the features so, that writing custom components for it does not get too complex. There’s also the issue of the template compiler: you can’t really parse all of those on each page request, so the custom components would require an easy way to tell the compiler what it has to do to be able to compile them.

I think a template engine should perform more tasks for you and not expect them from you. Similar to having a higher-level programming language, the template engine should be a higher-level language for writing templates more efficiently and so that the result is easier to manage.

It should be about making the programmer more effective – not about safeguarding him from writing PHP inside the templates because it’s “bad”.

Please share your thoughts on the examples. Also, how would you improve writing templates?

Further reading:
On template “Tag Soup”
Different PHP template engines

Share this:
  1. 37 Responses to “What would make template engines actually useful?”

  2. Are you inventing XSLT?

    By Sam on Jan 19, 2009

  3. Now why would I do that?

    Seriously speaking.. XSLT is really verbose, and it doesn’t really do any of this kind of “automatical” things I was talking about here.

    By Jani Hartikainen on Jan 19, 2009

  4. It does more. You can define subtemplates for striped tables, lists… even for gallery and then use them as many times as you want.

    In terms of scalability and not repeating your code it’s ideal.

    In terms of speed and learning curve — not.

    By Sam on Jan 19, 2009

  5. Examples provided here are somewhat the same to calling XSL templates with parameters.

    By Sam on Jan 19, 2009

  6. The keyword is somewhat. The thing with XSL is that you end up with lots of XSL template markup, and it can be difficult to grasp as the markup is complex. The way I’m proposing would be much simpler, and it would assume sensible defaults, so you would not need to customize it except for special cases.

    By Jani Hartikainen on Jan 19, 2009

  7. XSLT is way too verbose to use. And once your stylesheet grows beyond dozen of templates, it starts to get messy and hard to debug.

    With PHPTAL you could use tal:attributes to conditionally insert class, so you wouldn’t have to repeat another set of rows.

    Or instead of tpl:type=”first” you could use tal:condition=”repeat/x/start” and tal:condition=”not:repeat/x/start” on the second set of rows.

    You get savings from not specifying which table cell gets what data, but OTOH such automagic works only if you have exactly matching table as data source.

    By kl on Jan 19, 2009

  8. The most similar engine to this idea is probably PHPTAL. However, the key difference here is that this one would be designed around making you more effective in writing templates – even more so than other engines.

    For example about what kl said of the table stuff: the reading of values from the array could be customized using some other attribute or perhaps using the default values in the tds as a hint: type getName into the td, and it could guess that you want to call getName on the object it’s using.

    By Jani Hartikainen on Jan 19, 2009

  9. Hi Jani

    IMO only XML based template engines like PATtemplate are worth of trying.

    1. It’s easier to learn, since designers should know basics of XML.
    2. It’s IDE friendly – code-completion is possible; WYSIWYG as well.
    3. As you noticed, different kind of helpers could be painlessly embedded into existing HTML document via namespaced attributes or tags.

    Cheers, Alan

    By Alan on Jan 19, 2009

  10. I did mistake. I meant PHPTAL, not PATtemplate :)

    By Alan on Jan 19, 2009

  11. Point 1 should not apply: what I want as a programmer who is perfectly capable of doing templates in PHP etc. is something that would simplify the common tasks involved in templates – Similar to how you would expect a framework to simplify other programming tasks. This is something current template engines don’t do.

    By Jani Hartikainen on Jan 19, 2009

  12. You see – I’m looking at template engines as some kind of connector between designer and developer.
    If your work doesn’t require distinction like that, I think PHP-based TE (or PHP itself) are perfectly suitable.

    By Alan on Jan 19, 2009

  13. It is suitable, but why does it have to be so tedious when we could have a tool that does some of the work for us?

    By Jani Hartikainen on Jan 19, 2009

  14. Why not to use helper objects?

    By Sam on Jan 19, 2009

  15. Sam, I mentioned before that not every designer is also PHP programmer.

    By Alan on Jan 19, 2009

  16. Alan, why designer should even write a line of markup?

    And if he is writing templates, why template engine is better than php? You need to teach him template language or 4-5 PHP commands anyway.

    By Sam on Jan 19, 2009

  17. Jani, in that case I still vote for XML abstraction over HTML. It is more elegant than Smartish pseudo-code.

    By Alan on Jan 19, 2009

  18. I believe the templating engine Dwoo http://dwoo.org has most of the features you mentioned. It even has some features borrowed from Django templates.

    By ejunker on Jan 19, 2009

  19. Yes – it has the features of a typical template engine, but none of the features that would make it reduce the amount of code I need to write

    By Jani Hartikainen on Jan 19, 2009

  20. One thing that template languages like Smarty also do is to reduce complexity. For example writing something like this with smarty:
    {cache time=$expire}
    // … content …
    {/cache}
    plus help you to create your own html dsl :)

    By Radoslav Stankov on Jan 19, 2009

  21. PHP already IS a templating tool. Anything else is cruft.

    If you have to teach you designers to use smarty syntax they will not have learned anything useful or scalable.

    Teach them (with a few basic examples; variable injection, loops, etc.) the very limited subset of PHP needed to populate some template HTML and you have given them a skill set to build on.

    What if your 3rd party template engine goes the way of the dodo? You’ll have to train them all again…

    By Richard@Home on Jan 20, 2009

  22. Some of these comments make me wonder if people even read the post completely before commenting :P

    By Jani Hartikainen on Jan 20, 2009

  23. I’m a Smarty fan myself. I feel it does everything suggested here:

    Alternate Row Colors : This certainly does “actually significantly reduce the amount of code needed to write some common scenarios”

    My only complaint with Smarty is the output. I just can’t make it produce clean HTML. If you look at my site’s source, you’ll run away screaming. All the indenting is off, many lines wrap, etc.

    By AppBeacon.com on Jan 20, 2009

  24. I use Smarty myself and although I like your idea for a template engine I miss the possibility of just assigning a variable for usage in the template and the possibility of just calling a method on an object outside a tag. I usually break up my pages in different parts en make different templates for them, which I call through a method on an object.

    Any idea’s on how to accomplish this kind of behaviour in your proposed engine?

    By Timo on Jan 20, 2009

  25. You’re forgetting one thing:

    Less markup is a bad thing when it comes to readability. With Smarty / PHP you can see what will happen. With your proposal not so much.

    By Tinus on Jan 20, 2009

  26. Timo: a custom tag, a PHP snippet? Whatever would work the best =)

    Tinus: if you don’t understand PHP you don’t know what it’s doing no matter how many lines there are. If you understand the markup, you will know what it does, and since there’s less markup to consume to understand it, I think it’s easier – provided you know what everything does.

    By Jani Hartikainen on Jan 20, 2009

  27. this is so good to me,so i know and can be learn directly..

    By angga on Jan 20, 2009

  28. this is ok

    By angga on Jan 20, 2009

  29. I prefer using “raw” php for templating (mostly with helper objects); PHPTal feels like aspx .net imho; I liked Dwoo loops though.

    I prefer to treat templating as something “not too complex”: alternating rows, loop iterators, custom xml-like components are nice, but I can totally leave without them :)

    By deadcabbit on Jan 22, 2009

  30. I mean live without, sorry for my terrible English :(

    By deadcabbit on Jan 22, 2009

  31. I’ve been looking for a template engine for Zend which allows my to simply type {{var}} and convert it to echo $this->escape($this->var) for me. Smarty seems overkill for this, and I don’t see an easy way for me to call view helpers with it. So I made my own. Looking forward to see your engine, I’d use it in a heartbeat.

    By mz on Jan 23, 2009

  32. (Without having looked at Dwoo yet) I predict the best template language will be built with Tobiasz Cudnik’s amazing phpQuery. Take a look at QueryTemplates for one.

    By Steve Clay on Jan 23, 2009

  33. QueryTemplates looks interesting, but I think it has one major flaw: the logic related to the markup is not in the same file as the markup itself. While this may be desirable on a certain level, I feel it may easily lead to confusion and make it more difficult to change the end result, as you will have to go into two files and change them both.

    By Jani Hartikainen on Jan 23, 2009

  34. Hi Jani, interesting things you have here.

    > QueryTemplates looks interesting, but I think it has one major flaw: the
    > logic related to the markup is not in the same file as the markup itself.

    QueryTemplates can be in a single file by various of ways and with latest version of phpQuery, it may be achieved in 3 lines of code. Like this:

    Hello world

    sourceCollect($markup, ‘markup’)
    ->parse()
    ->source(‘markup’)->returnReplace()
    ->find(‘p’)
    ->text(‘Hello template!’)
    ;

    The last part is targeted to look like this:

    require template(‘test’)->parse($markup)
    ->find(‘p’)
    ->text(‘Hello template!’)
    ;

    > While this may be desirable on a certain level, I feel it may easily
    > lead to confusion and make it more difficult to change the end result, as you will have
    > to go into two files and change them both.

    There is also a possibility to do it only one time, at “the third place”, which would be some above layer of filtering output. Then rest of the source could be untouched.

    I’ve also done some mockups of new APIs regarding you Case examples from the post. Those are “tables” and “filtering”.
    It could be done with QueryTemplates like this:

    template(‘table’)->parse(‘table.html’)
    ->find(‘table > tr’)
    ->loopOne(‘rows’, ‘i’, ‘row’)
    ->varsFilter(‘htmlentities’, ‘stripslashes’)
    ->varsToSelector(‘row’, $rowFields)
    ->tableFirstRowClass()
    ;

    Where “tableFirstRowClass” of course isn’t part of core API, it has to be declared. There are really 2 possible ways of doing this:
    // EXTENDING PHPQUERY
    $newMethods = array(
    ‘tableFirstRowClass’ => create_function(‘$self’, ‘
    $self->addClass(“if ($i == 0) print \’first\’”);
    return $self;
    ‘)
    // will be like this in PHP 5.3
    // function($self) {
    // $self->addClass(“if ($i == 0) print ‘first’”);
    // return $self;
    // }
    );
    phpQuery::extend(‘phpQueryObject’, $newMethods);

    // EXTENDING SCRIPTS
    // self, $params, $return, $config
    phpQuery::script(‘tableFirstRowClass’, create_function(‘$vars, $className = “”‘, ‘
    vars_extract($vars);
    if (! $className)
    $className = “first”;
    $self->addClass(”
    if ($i == 0) print \’$className\’;
    “);
    ‘));

    Remember those are just a mockups, it’s not yet available. I think i will implement them in this week.

    And what does about… you called it “More on different attributes”. In QueryTemplates this is called varsToSelector and other varsTo… methods (which actually working only with variables, but adding function support is possible). But instead of
    > tpl:var=”title”
    it needs to be written as class=”title” or class=”custom-prefix-title” or any other queriable, even tpl:var=”title” itself…

    By Tobiasz Cudnik on Jan 24, 2009

  35. Thanks for the elaborate explanation Tobiasz. I will probably have to try QueryTemplates to come to a better conclusion about it, as right now I have kind of mixed feelings about it, but I don’t want to judge it based on just that.

    On one hand, it seems useful in the way that you can declare the processing separate of the markup itself, but on the other hand it seems to go much more into the code-which-looks-like-PHP-mixed-into-HTML which I kinda don’t like.

    By Jani Hartikainen on Jan 24, 2009

  36. Jani -> Actually, Open Power Template 2 provides a template language similar in concepts to those mentioned in your post. There is auto-filtering with smart control, specialized loops for column displaying, tree rendering, HTML form building and everything that you need in templates without dealing with the implementation details.

    By Zyx on Feb 28, 2009

  1. 2 Trackback(s)

  2. Jan 20, 2009: links for 2009-01-20 « Richard@Home
  3. Jan 23, 2009: Three PHP mistakes that will cause you debugging nightmares | CodeUtopia

Post a Comment

You can use some HTML (a, em, strong, etc.). If you want to post code, use <pre lang="PHP">code here</pre> (you can replace PHP with the language you are posting)