Templates are a great way to separate logic from presentation in an application. There’s no shortage of template engines available for PHP, so why would you want to write another one? Well, because sometimes you don’t need a full fledged template language like smarty, and writing your own simple engine is as easy as it is useful.

When I wrote the impress wordpress plugin (which calculates some simple blog stats - see the bottom right of this page) I wanted to make it very easy for bloggers to configure. The obvious solution was to create a function for each statistic, and let the user call these functions from their template files. With this approach you end up with code like the following:

<p>So far I've written <?php echo impress_wordcount(); ?>
words in <?php echo impress_posts(); ?> posts. <php echo
impress_comments(); ?> comments have been posted, with a total
of <php echo impress_comment_wordcount(); ?> words.</p>

It works, but it’s not that maintainable. And it’s a pain in the ass to write.

To simplify things I implemented a simple template engine that makes configuration a snap. Instead of strategically placing clumsy function calls within HTML, users call a single function that takes a specially formatted string, expands certain keywords (the template variables), and prints the result. The new code looks like this:

<p><?php impress("So far I've written :post_wordcount words
in :posts posts. :comments comments have been posted, with a total
of :comment_wordcount words."); ?></p>

Template variables begin with a colon, and consist of upper or lowercase letters and the underscore character. You could easily modify the code to allow additional characters in variable names, or to use different delimiters. The best part is that it took only a few lines of code to implement:

function impress( $format=':post_wordcount' ) {
  echo preg_replace_callback('/:([a-zA-Z_] )/',
           'impress_callback', $format);
}

function impress_callback( $matches ) {
  $function = 'impress_'.$matches[1];
  if(function_exists($function)) {
     return call_user_func($function);
  }
  return $matches[0];
}

The preg_replace_callback() function is a savior here. It searches for text matching a pattern (the first argument), in the subject string (the third argument). For each match it invokes a callback function (the second argument), passing the matched text as an argument. The callback function first checks that a function exists for the matched template variable. If it exists, the function is called and the result is returned. Otherwise the template variable is returned unchanged.

I’ve used simple templates like this one in a number of projects. They’re simple to implement, and make configuration and maintenance a breeze.