Programming in Sitellite
Chapter 4: SimpleTemplate in Depth
SimpleTemplate is one of two template engines in Sitellite. The other, XT, is an XML-based template language used to render the design templates for the web site. SimpleTemplate, on the other hand, is used for smaller output, such as the formatting of search results or news stories. The reason for the two, instead of the usual one-size-fits-all template language which is what most frameworks offer, is that we were able to better tailor each for its intended use.
SimpleTemplate allows you to create small templates fast. Its syntax is not overly complex, and it has none of the XML verbosity that XT does. This makes it ideal for programmers to use to format the output of database queries and other user interface needs.
The basics
As we've seen from the above examples, SimpleTemplate templates are saved to '.spt' files in the 'html' folder of each app.
The basic tags that can be used in the template correspond to the key names or property names of the associative array or object passed to the template_simple() function. So if the array contains the keys 'id', 'name', and 'description', then the main tags are {id}, {name}, and {description}.
Loops
To loop in SimpleTemplate, we use the {loop expression}...{end loop} syntax. An example of this is:
<ul>
{loop obj[items]}
<li>{loop/_value}</li>
{end loop}
</ul>
The obj[items] means "loop through the array stored in the 'items' key of the array passed to the template". 'obj' represents the array or object passed to the template. Similarly, if we passed an object to the template, obj[items] would become obj.items. These are both a shorthand way of saying $obj['items'] and $obj->items respectively, which makes it easier to read within a template.
We refer to the current loop item via {loop/property} where 'property' is some property of the current loop item. {loop/_value} is one of several properties available in any SimpleTemplate loop, because they are created by SimpleTemplate itself. These include:
- {loop/_key} – The array key of the current loop item. This could be a number or a string.
- {loop/_index} – The numeric index of the current loop item. This is always a number and is not the same as the key.
- {loop/_total} – The total number of items in the loop array.
- {loop/_properties} – An array of properties of the current loop item.
- {loop/_value} – The value of the current loop item.
Conditions
Conditional execution can be done in SimpleTemplate via the {if expression}...{end if} syntax. This syntax is illustrated in the following two examples:
{if obj[some_value]}
<p>{some_value}</p>
{end if}
This condition checks for the 'some_value' property before attempting to output it. The next example outputs something else if the condition evaluates to false. The {if else} tag tells SimpleTemplate to match the opposite of the previous {if expression} tag. There is no 'else if' tag.
{if obj[some_value]}
<p>{some_value}</p>
{end if}
{if else}
<p>No value.</p>
{end if}
More complex expressions can also be made in {if} and {loop} blocks using a shorthand syntax defined in the SAF API references under saf.Misc.PHPShorthand. Here are a few examples.
{if obj.property eq 'foo'}
<p>{property}</p>
{end if}
{if obj.property gt 5}
<p>{property}</p>
{end if}
{if not empty (obj.property)}
<p>{property}</p>
{end if}
Multiple loops
Say you want to loop through a list of people and each one has a 'cities' property that contains a list of the cities they've lived in, as well as a 'city' property containing the city they currently live in. You could loop through the people and highlight their current city by comparing it to the city value in the parent (people) loop like this:
{loop obj[people]}
<h2>{loop/name}</h2>
<ul>
{loop loop.cities}
<li>{loop/_value}
{if loop._value eq parent.city}- Current{end if}
</li>
{end loop}
</ul>
{end loop}
Output filters
By default, SimpleTemplate passes all tag values first through the htmlentities_compat() function defined in saf.Functions. This adds an extra level of security by reducing the chance of cross-site scripting attacks from succeeding. However, you can also specify your own filters in the following ways. Filters are simply PHP functions, either built-in or defined by you in your app.
Default - passed to htmlentities_compat():
{some_value}
Using an alternate function:
{filter strtoupper}{some_value}{end filter}
Using multiple filters - evaluated outward, so nl2br is first:
{filter strtoupper/nl2br}{some_value}{end filter}
Using an alternate filter on multiple tags:
{filter strtoupper}
<h1>{name}</h1>
<p>{description}</p>
{end filter}
Disabling all filters:
{filter none}{some_value}{end filter}
Filter shorthand for a single item:
{some_value|strtoupper}
Filter shorthand with multiple filters - evaluated outward again:
{some_value|nl2br|strtoupper}
Additional tags
Beyond looping, conditions and output filtering, SimpleTemplate has a number of additional features for template developers, listed with examples below.
{exec} and {php}
To output a PHP expression, which can be useful for testing, use the {php} tag. Alternately, to execute an expression with no output, useful for simple inline PHP statements, use the {exec} tag.
{php obj[some_value]}
{exec obj[some_value] += 1}
{intl}
To mark hard-coded text within a template so that it can be translated for multilingual sites, use the {intl} tag.
{intl This text can be translated.}
This text cannot.
{alt}
The {alt} tag is a handy reference to the saf.Misc.Alt library, which helps you easily alternate between items in a list. This is mainly used to create alternating background colours for tables.
{alt odd even}
<table>
{loop obj[items]}
<tr class="{alt/next}">
<td>{loop/_key}</td>
<td>{loop/_value}</td>
</td>
{end loop}
</table>
Boxes
Just like you can import boxes from other boxes, you can also call boxes directly from within a SimpleTemplate file. Here's a simple example, another that passes parameters to the box, and a third that passes the template data object itself as a parameter of the box.
Output a dynamic breadcrumb menu from the 'sitellite' app:
{box sitellite/nav/breadcrumb}
Output the helloworld box from our previous examples:
{box myapp/helloworld?name=Joe}
Output the standard Sitellite editing buttons for the web view:
{box cms/buttons?collection=myapp_listing&object=[obj]}
Registering multiple objects
So far, we've been working with 'obj' and 'loop' as the built-in objects available to SiteTemplate. We've also briefly used some global objects. But what if we want to pass multiple objects to the template that aren't in the global namespace? We can do this in our box code by calling the template_simple_register() function just before calling template_simple().
<?php
loader_import ('myapp.Objects');
$product = new Product ($_GET['id']);
$category =& $product->getCategory ();
template_simple_register ('category', $category->makeObj ());
template_simple ('register_test.spt', $product->makeObj ());
?>
We can now refer to 'obj' to access the product details, and to 'category' to refer to the category details.
<p>Product name: {name}</p>
<p>Category name: {category/name}</p>




John Luxford