HTML"> PHP"> XHTML"> XML"> ]> PHP templates: Smarter sans Smarty

&PHP; templates:
Smarter sans Smarty

At one time, I got all up and excited about Smarty, so I rewrote a lot of &PHP; code to use Smarty templates.

Of course, this was only after I had already rewritten this code to abuse object orientation in the worst of possible ways. To imagine the extend of this horridness, imagine a class for each screen, all derived from the same Screen superclass. Each class had to implement the display() function, which contained, verbatim, all the HTML tag-soup to throw upback at the browser. I don't think anyone will be surprised when I say that throwing Smarty in the soupmix didn't make it taste that much better.

Of course, learning, extending, working around and getting increasingly frustrated with Smarty was fun, but as much as it was fun, it was also a complete and utter waste of time.

Why? What's wrong with Smarty?

There's nothing wrong with Smarty. It's very well written, works without a glitch and serves its purpose just fine. &PHP; itself, however, serves this purpose even better. Because, in the end, &PHP; still is a templating language. &PHP; is also a very complete templating system. I mean, it has to be if it even lets you invent your own templating language. But, just that you can doesn't mean that you should.

The smarts of Smarty

Easy variable substitution

Most of the time in a templating language is spent spitting out variables.

Variable substitution in Smarty

<body>
  <p>Hi {$person.name},</p>
</body>

Variable substitution in &PHP;

<body>
  <p>Hi <?php echo $person['name'] ?>,</p>
</body>

If $person['name'] equals Rowan, both examples will generate the following &HTML;:

<body>
  <p>Hi Rowan,</p>
</body>

Which of these looks better is mostly a matter of taste. Related to taste, it should be mentioned that the &PHP; example could be abbreviated to the following if you have enable_short_tags enabled (which I wouldn't recommend for the same reasons as why I don't like the syntax of most templating languages):

<body>
  <p>Hi <?= $person['name'] ?>,</p>
</body>

The question of which one of the two works better can be answered by applying Occam's Razor: why add unnecessary cruft to your process if the same result can be achieved without?

Explicit variable assignments

With template languages such as Smarty, you need to explicitly assign each variable that needs to be available from the template. This is usually tauted as a feature, because it forces you to think before you start throwing data at you presentation templates.

Assigning variables for the use in Smarty is easy.

<?php
 
# Fetch something from the DB
$person = mysql_fetch_assoc($result);
 
# Assign the associative array $person to the smarty variable $person.
$smarty->assign('person', $person);
 
?>

But, without Smarty, it's easier still.

<?php
 
# Fetch the same something from the DB
$person = mysql_fetch_assoc($result);
 
?>

If you really want the kind of strict separation as encouraged by a templating system, it can be achieved much easier without one. Just include() or eval() your templates from within the scope of a function or method and you can exactly define what you want access to. (Somewhere below, I provide a list of &PHP; frameworks that support view/controller separation without requiring custom syntax.)

Variable modifiers?

So what are variable modifiers? They're some sort of pipe-like notation for a restricted set of functions.

Variable modifiers in Smarty ...

<ul>
  <li>E-mail addy: {$email|escape:"html"}</li>
</ul>

... are simply functions in &PHP;

<ul>
  <li>E-mail addy: <?php echo htmlentities(PERSON_EMAIL) ?></li>
</ul>

You can add variable modifiers by writing a Smarty plugin according to a well-defined plugin interface. But, why bother if you can already add functions to &PHP; through a well defined function definition interface?

This Smarty plugin definition is just a cumbersome version ...

<?php
 
function smarty_modifier_leetspeak($string)
{
  return str_replace('aelz', '4312', $string);
}
 
?>

... of this similarly simple &PHP; function.

<?php
 
function leetspeak($string)
{
  return str_replace('aelz', '4312', $string);
}
 
?>

Traversing arrays

Traversing arrays in Smarty

<body>
  <h1>People list</h1>
 
  <ol>
    {foreach from=$persons item=person}
      <li>{$person.name}</li>
    {/foreach}
  </ol>
</body>

Traversing arrays in &PHP;

<body>
  <h1>People list</h1>
 
  <ol>
    <?php foreach ($persons as $person): ?>
      <li><?php echo $person['name'] ?></li>
    <?php endforeach ?>
  </ol>
</body>

Advantages of using &PHP; as a templating language

Familiar syntax and functions

No need to learn separate syntax depending on the templating system of the day. Just stick with familiar &PHP; syntax, or, if you don't know &PHP; syntax, learn a skill which is actually portable across projects and jobs.

&XML; compliant <?php ?> processing instructions

Thanks to &PHP;'s compliance to &XML; processing instructions, &PHP; can be used in any part of the &XML; toolchain. E.g.: it's easy to process &XML; code that contains &PHP; using XSLT or any other XML-PI-aware tool.

Reasons to still use Smarty and why they're all wrong

You can't use &PHP; for templates, because template designers don't know &PHP;

wildleaf on Digg refutes this argument nicely:

So instead of teaching them minor &PHP; (such as simple loops and how to print out variables with a $ in front of them) you will tell them to put in a specially formatted HTML comment or some sort of ##VARIABLETOPRINT## that they will paste all over the place. How is any templating language any easier than basic template based &PHP;?

&PHP; syntax is pretty simple and consistent and everything related to outputting and formatting stuff can be done with simple functions without having to learn anything about more complicated issues such as object architecture.

In the same Digg discussion, Joel Hardi takes the argument even further:

Yeah, all these crappy template languages are a solution looking for a problem, just developers scratching an itch.

I would love to never have to learn another one, but instead every CMS developer has to invent a half-declarative, half-functional templating language that winds up taking acres of time even for developers to learn—let alone the graphic designers and other folk these templating languages are supposed to be dumbed down for. And your typical HTML-savvy designer would much rather pick up a some inline PHP skills to put on the résumé than learn some obscure templating pseudocode.

Indeed. If you, as a designer, were to add a skill to your résumé, which would you rather add: (Obscure) templating language X or experience with &PHP;?

Separation of the business logic and presentation logic

Yeah, presentation logic. Some templating languages have you define blocks, the behaviour of which you then still have to define in your code.

The nonsense of this argument is so obvious that it shames me that it took me a lengthy trip through template territory to acknowledge the simple truth: there is noöne stopping me from putting all presentation-related code in its own little layer, and this is, in fact, what the newer &PHP; frameworks and template systems do.

Hans Zaunere's, in A Tale of Three Templates:

Web pages have become so complex that a certain level of logic is required within HTML, which is underscored by the fact that the external templating engines have this functionality.

  • Templating engines were created to reduce the bad practice of putting business logic, database queries, and other complex operations, directly inline with HTML.
  • Proper page architecture, and the separation of presentation logic from complex logic make external engines superfluous.

Buzzword compliance

You really do a need a separate template language because of buzzword compliance? Then I suggest going for a level of buzzword compliance which can only be found in XSLT.

Proponents and opponents of this approach

Of course, most of the arguments used here didn't come from me, myself or I.

Frameworks using pure &PHP; templates

Finally, you may want to take a look at my own simple function for applying pure PHP templates.


Discuss this article on Digg or on reddit.