Simple Templating Language in PHP

A few years back, there was a trend in the PHP community to make alternative templating languages that ran inside PHP. This was so the designers could create HTML templates, and include bits of code to display data. The best was probably Smarty.

After a while with this, a counter-trend emerged, of rejecting adding yet-another-language to the system. After all, PHP was a templating language. Some web frameworks used PHP as the templating language, but simply asked that only a tiny subset of the syntax be used. CodeIgniter and Savant did this. (So did the never released Slaptech code generator.)

I was firmly in this latter camp. There are already too many languages involved with PHP: PHP, Javascript, HTML, CSS, and xml. Templating systems are slower, too.

The world has changed, though. Today, due to AJAX, you need to produce lists of data encoded into xml, or into fragments of HTML.

You can easily do this with regular PHP... except that PHP can sometimes look sloppy, and leave you wanting a simple templating language. What's below is an extremely limited templating language, implemented in a single function.

Additionally, there are two more functions that will apply the template to arrays and iterators.

If you copy this code to a file, and run it on the server, it'll demo each function. More programming blather after the code.

<?php
# an extremely minimalist templating language
#
# $tpl = 'text{interpolate}text';
# $output = tpl_merge( $tpl, array('interpolate'=>'text'));
# // $output is 'texttexttext'.
echo tpl_merge'Hello, {name}.', array( 'name' => 'world' ) );

function 
tpl_merge($t$v)
{
    
$o $t;
    
$find = array();
    
$repl = array();
    foreach(
$v as $var=>$val)
    {
        
$find[] = '{'.$var.'}';
        
$repl[] = $val;
    }    
    
$o str_replace$find$repl$o );
    return 
$o;
}

echo 
tpl_merge'<p>Hello, {name}.</p>', array( 
                                         
'name'=>'{first} {last}',
                                         
'first'=>'Joe',
                                         
'last'=>'Blow',
                                        )
                                    );

# a template merger that applies the template to an array of arrays.
echo tpl_merge_array'<p>Hello, {name}.</p>'
                                array(
                                    array( 
'name'=>'John',),
                                    array( 
'name'=>'Rosa',),
                                )
                            );

function 
tpl_merge_array$t$a )
{
    foreach(
$a as $element)
        
$o .= tpl_merge$t$element );
    return 
$o;
}

# A similar template merger that works with iterators.
# An iterator is defined, minimally, as an object that has a next() method
# that returns the next item, and null past the last element.

$c = new Collection();
$c->add( array( 'name' => 'Gloria' ) );
$c->add( array( 'name' => 'Steve' ) );
echo 
tpl_merge_iterator'<p>Hello, {name}.</p>'$c );

class 
Collection {
    var 
$a;
    function 
Collection() { $this->= array(); }
    function 
add$a ) { $this->a[] = $a; }
    function 
reset() { reset($this->a); }
    function 
next() { 
        
$val current($this->a);
        if (
null===key($this->a))
            return 
false;
        
next($this->a);
        return 
$val;
    }
}

function 
tpl_merge_iterator$t$it )
{
    while( 
$a $it->next() )
        
$o .= tpl_merge$t$a );
    return 
$o;
}

So, clearly, you can use these functions to build pages in a functional-language style. Just define templates and immediately apply them to iterators that wrap around queries. Producing html or xml from queries is simplified. Best of all (for me) you can write more code in a functional style than in the dreaded OO style.

echo str_merge_iterator( 'template{here}', query('select here from foobar where here>100') );

It's not really that terse, but, the idea is, you're not writing any more loops. All that is hidden.

.