Recent changes RSS feed
 

Template View

A template is a document typically HTML with embedded markers which are replaced, manipulated, or evaluated via a template engine API to produce an output document.

A Template View uses a template to implement the View portion of the Model View Controller pattern.

NOTE: The Template View pattern should not be confused with the Transform View pattern which is implemented by XSLT style transformations.

Separating HTML from Programming Code

The purpose of a template is to isolate the HTML from the programming language code in a web application. There are several reasons for such a separation.

HTML Design and Application Programming are different skills

HTML Design and Application Programming are different roles on a web application development team, often performed by different people and at different points in time. Separating the HTML from the code gives each person their own file to work on.

Development Tool Support

When HTML was designed, it was never intended to be directly edited. Separating HTML from programming code allows the large body of WYSIWYG HTML editors to be used to edit template documents.

Presentation Logic and Templates

Simply separating HTML from programming code goes a long way toward isolating the presentation layer of an application. However, Presentation Logic complicates this isolation. Presentation Logic consists of requirements such as “Show negative balances in red.”

A key design decision when using Template View is how to handle Presentation Logic.

HTML was specifically not designed to be able to handle arbitrary logic see Principle of Least Power. To be able to handle arbitrary presentation logic, one must either augment the HTML or place the logic inside the program.

Presentation Logic in the Application

To preserve the Model View Controller pattern, presentation logic should not be mixed with other kinds of logic in a program. Helper objects can be used to hold Presentation Logic and keep it separated. Components in a component based API are an excellent place for Presentation Logic to reside.

Presentation Logic in the Template

Broadly speaking there are two paradigms for representing logic. One is declarative and the other is imperative. In the declarative style, you define what it is that should be computed. In the imperative style you define how the computation should be done. see Declarative Vs Imperative Programming

Most popular computer programming languages follow the imperative style, including both PHP, C, and Java. Popular declarative languages include SQL and HTML.

Programming languages differ in how powerful they are, that is which kinds of problems they can solve and how many types of problems they can solve. see Turing Complete. HTML is so underpowered that it isn’t even really considered a programming language.

Fortunately, it is not necessary to have a full power programming language to embed Presentation Logic in your templates. The advantage to using a full powered language is flexibility. Anything you can conceive of doing can be done inside the template. The price is complexity. Programmers are used to dealing with the complexity of programming languages, while HTML designers may not be and may even be intimidated by the notation. The more powerful the logic capabilities of the template are, the more independence the template designer gains from the application designer. At the same time, the more powerful the template language, the fewer people are capable of using it. Embedding any logical constructs at all in templates crosses a threshold which greatly reduces the number of people with the potential to edit them.

Because of the declarative/descriptive nature of HTML, a declarative syntax for Presentation Logic can be a good match. The combination of a low power declarative syntax for Presentation Logic would be the most HTML designer friendly.

Here is an example of an imperative template fragment taken from the TikiWiki project using Smarty:

{if $prev_offset >= 0}
[<a class="prevnext" href="tiki-webmail.php?section=contacts&amp;find={$find}&amp;offset={$prev_offset}&amp;sort_mode={$sort_mode}">{tr}prev{/tr}</a>]&nbsp;
{/if}
{tr}Page{/tr}: {$actual_page}/{$cant_pages}
{if $next_offset >= 0}
&nbsp;[<a class="prevnext" href="tiki-webmail.php?section=contacts&amp;find={$find}&amp;offset={$next_offset}&amp;sort_mode={$sort_mode}">{tr}next{/tr}</a>]
{/if}
{if $direct_pagination eq 'y'}
<br/>
{section loop=$cant_pages name=foo}
{assign var=selector_offset value=$smarty.section.foo.index|times:$maxRecords}
<a class="prevnext" href="tiki-webmail.php?section=contacts&amp;find={$find}&amp;offset={$selector_offset}&amp;sort_mode={$sort_mode}">
{$smarty.section.foo.index_next}</a>&nbsp;
{/section}
{/if}

An alternate declarative version of the same fragment using components and custom tags might be:

<!-- example component based page navigator from WACT.  Does not exactly correspond to the above -->
<page:navigator id="pagenav" items="20">
    <page:first>First</page:first> <page:prev>Prev</page:prev>
    <page:list>
        <page:number>
        <page:elipses>...</page:elipses>
        <page:separator> </page:separator>
    </page:list>
    <page:next>Next</page:next> <page:last>Last</page:last>
</page:navigator>

There are reuse implications for imperative versus declarative styles. With the power of an imperative syntax available, it is easy to continuously re-invent the wheel. The previous code structure appears at least 89 different times in the TikiWiki template code according to grep. Should a change to this structure be needed, it will have to be changed in 89 places. If a declarative custom tag marker with a component API was used, some changes might only have to be made in one place.

This is much more of an indictment of the tiki programmers than the Smarty solution. This easily could have been written as a custom plugin, where the call 89 times would have been {pager page=page next=next data=data} - Jason

It could have been but wasn’t. The point is that having the imperative syntax available doesn’t encourage people to think in terms of the domain - Jeff

Marker Styles

Markers are one half of the bridge between templates and code. Markers appear in the HTML template and represent places where template data can be manipulated or where application data can be inserted into the template.

Any type of marker may be used for declarative statements, except Scripting Tags, which are always imperative. Any type of marker may be used for imperative statements except Strict HTML, which is inherintly declarative.

Most template engines use a mix of the different marker styles.

Strict HTML

In this style, all markers are valid HTML. Elements are typically identified by their ID attribute and the template is parsed with XML like parser capable of handling badly formed XML HTML. This approach is the cleanest as far as development tool support. I am not aware of a PHP tool to support this approach. Xmlc supports this approach in Java.

Attribute Language

Template logic is placed in the HTML tags themselves using custom attributes for example

<table>
  <tr tal:repeat="item here/cart">
    <td tal:content="repeat/item/index">1</td>
    <td tal:content="item/description">Widget</td>
    <td tal:content="item/price">1.50</td>
  </tr>
</table>

Custom attributes take advantage of the recommendation in the HTML Specification that “If a user agent encounters an attribute it does not recognize, it should ignore the entire attribute specification i.e., the attribute and its value” Thus many HTML editing tools preserve or ignore extra attributes, even if they are not capable of adding them or editing them.

Zope’s Template Attribute Language uses this approach ported to PHP as phpTal.

Pros

it’s valid XML and XHTML, because the “tal:”-part of the attribute designates a new namespace.

Cons

must learn the syntax, it is unlikely to be supported by development tools and is not valid HTML.

Custom Tags

Additional tags are defined which become mixed with HTML.

This is a popular approach with Java. Java has an extension mechanism for Java Server Pages which allows programmers to create Tag Libraries, which are collections of custom tags.

Custom tags take advantage of the recommendation in the HTML Specification that “If a user agent encounters an element it does not recognize, it should try to render the element’s content.” Thus many HTML editing tools preserve but ignore custom tags, even if they are not capable of adding them or editing them.

Here is an example of using custom tags from Wact to display a list of form error messages:

<ERRORSUMMARY name='Summary'>
<list:LISTITEM><FONT COLOR="RED">{ErrorMessage}</FONT><list:SEPARATOR><BR></list:SEPARATOR></list:LISTITEM>
</ERRORSUMMARY>

Pros

Support in Java and .NET means good editor support?

Cons

Can be tricky to implement a middle layer between Domain Logic and Presentation Logic.

Simple Placeholders

This style uses a minimal custom template syntax to enforce a much stricter separation of presentation and logic than more complex template languages.

For example, PEAR’s HTML_Template_IT uses just two custom elements: curly braces enclose variables, and comment tags denote the start and end of logical units within the template.

<!-- BEGIN loginTable -->
<table>
  <!-- BEGIN headerRow -->
  <th>
    <td>Username</td>
    <td>Password</td>
  </th>
  <!-- END headerRow -->
  <!-- BEGIN dataRow -->
  <tr>
    <td>{username}</td>
    <td>{password}</td>
  </tr>
  <!-- END dataRow -->
</table>
<!-- END loginTable -->

Explained in more detail in Templates Revisited on PHPBuilder. Also implemented by HTML_Template_Sigma and Smart Template.

Pros

Being valid HTML, it enforces seperation of View from Controller and Model and it’s generally simple, placing little burden on page designers, inserting control logic into the XML in a hierarchical fashion.

Cons

Simplicity of the template has to be balanced by complexity in the underlying “binding” operation on the language. A PHP script which binds data to this template will typically be very “weighty”.

Template Languages

This approach implements some form of template programming language, separate from the underlying language, turning the latter into an interpreter or compiler for that language. For example

<table>
{section loop=users}
{strip}
   <tr bgcolor="{cycle values="aaaaaa,bbbbbb"}">
      <td>{users.name}</td>
      <td>{users.email}</td>
   </tr>
{/strip}
{/section}
</table>

Smarty and HTML_Template_Xipe use this approach.

Pros

It enforces seperation of View from Model and Controller

Cons

requires learning a new programming language, is unlikely to be supported by common development tools, debugging, profiling etc. must be implemented. Not valid HTML.

Scripting Tags

This approach uses the native language for templating. PHP was originally designed as a templating language for rendering output from underlying C/C++ code.

<table>
<?php
foreach ( $users as $user ) {
?>
  <tr>
    <td><?=$user->name()?></td>
    <td><?=$user->email()?></td>
  </tr>
<?php
}
?>
</table>

SimpleT and Savant use this approach as well as PHP itself of course.

Note: The usage of <?=var?> is only possible if PHP is configured to enable the short_tags directive in php.ini. For maximum compatibility it is best to always use the <?php echo var?> syntax.

Many of the previous templating approaches will “compile” the template into a native language for execution, for example Smarty compiles it’s template syntax into native PHP scripts which can be cached see PHP caching. WACT does the same. The native scripts are not intended to be edited directly though.

Pros

Is its very simple and fast, PHP syntax supported by many dev tools and debugging / profiling are handled by the PHP engine.

Cons

It requires discipline by the template design, not to might in other MVC layers into the template, some argue that designers don’t like PHP and PHP‘s security model safe mode does not make it possible to restrict templates to a limited subset of PHP functionality. It’s also not valid HTML. Requires knowledge of PHP, what is usually just an advantage for designer or webmaster. Limits templates to use just PHP, that means, that templates become development technology implementation dependent.

Template APIs

Template APIs are the other side of the code template bridge. The three API syles are like the three bears too coarse, too fine, and just right. The styles are:

Pinhole API

The template is presented to the code as a single object.

This is the papa bear of template API styles too coarse and probably the most common for PHP Template engines. It can feel a bit like constructing a ship in a bottle that is larger than the neck of the bottle. With this style of template API, you sometimes have to construct complicated arrays of arrays or use some sort of path language to push more complicated data structures through the simple API. The API is a narrow bottle neck for all of the data on the other side of it.

Here is a pinhole API example from HTML_Template_PHPLIB:

<TABLE BORDER="1" ALIGN="CENTER">
<!-- BEGIN ListItemBlock -->
<TR><TD>{Name}</TD><TD>{Description}</TD></TR>
<!-- END ListItemBlock -->
</TABLE>

The PHP code to populate the template with data and display it:

$T =& new Template_PHPLIB();
$T->setFile('page', 'list.ihtml');
$T->setBlock('page', 'ListItemBlock', 'WorkArea');
 
$result = mysql_query('SELECT * FROM phpmodules');
while ($row = mysql_fetch_array($result)) {
	$T->setVar('Name', $row['Name']);
	$T->setVar('Description', $row['Description']);
	$T->Parse('WorkArea', 'ListItemBlock', true);
}
 
$T->pparse('Output', 'page');

Compare this example to the Wact and Smarty examples of the same task in the Push vs. Pull section.

DOM API

XMLC is the only example I know of.

This is the mama bear of template API styles too fine. The DOM breaks up the template into very fine objects for example attributes of tags are represented as objects. This offers exquisite control over every detail of the template, but the API can be a bit too cumbersome.

Component APIs

Markers in the template are presented to the code as individual components. Usually only the elements in the template that need to be manipulated are marked.

This presents a medium grained object API that represents the template. Unneccessary detail is hidden, but you are not forced to manipulate everything in the template through a single object.

ASP.NET uses a component based API and Java is also trying to create a component based API called Java Server Faces. Web Objects is possibly the granddaddy of this approach on the web.

The Component based API style is particularly well suited for the custom tag and strict HTML marker styles.

Here is an example from Wact where HTML tags “map” to underlying runtime user interface components

   <select name="Fruit" id="Fruit">
      <option selected>these</option>
      <option>options</option>
      <option>are</option>
      <option>discarded</option>
      <option>later</option>
    </select>

Here is a php fragment which manipulates this component:

$View =& new Template("/selectexample.html");
$Fruit =& $View->findChild('Fruit');
$Fruit->setChoices(array('Apples', 'Oranges', 'Bananas'));

The id attribute of the select tag is used to uniquely identify the component in the template. No matter where the component is located in the template, findChild will retrieve it so that it may be manipulated.

Note that it’s common to have both native HTML tags and custom tags mapped to underlying classes. Microsoft, for example, have implemented classes for native HTML tags in the .NET System.Web.UI.HTMLControls namespace while custom web UI elements are implemented under System.Web.UI.WebControls. This allows native HTML elements, in particular forms, to be runtime components available to a Controller while custom tags act as “short cuts”, reducing the need for writing extensive HTML (such as a <table />).

Components enforces seperation of view from controller and model, while disguising template logic structures like loops in XML‘s tree structure. They also suits developers used to environments such as Visual Basic and allow for development tools such as Web Matrix helping web designers to drag and drop complex page elements.

Note: effectively Mozilla’s XUL is also a custom tag language, although it maps to an underlying Windowing component library rather than HTML rendering components.

Push versus Pull Data Population

Two styles of transfering data into the templates.

Push

All data is inserted into the template from the code via the Template API before the template is rendered.

Here is a push based on this Smarty with MySQL Tutorial:

<TABLE BORDER="1" ALIGN="CENTER">
{section name=i loop=$phpmodule}
<list:LISTITEM>
<TR><TD>{$phpmodule[i].Name}</TD><TD>{$phpmodule[i].Description}</TD></TR>
</list:LISTITEM>
{/section}
</TABLE>

The PHP code to bind the data to the template looks like this:

$List = array();
$result = mysql_query('SELECT Name, Description FROM phpmodules');
while ($row = mysql_fetch_array($result)) {
	array_push($List, $row);
}
 
$smarty =& new Smarty;
$smarty->assign("phpmodule", $List);
$smarty->display('list.tpl');

Notice that the data is iterated over twice. Once when it is pulled from the database and then again when the template goes to display it.

Pull

Bindings, callbacks, or events are used to allow the template API to request the data it needs during the process of rendering.

The advantage of a pull style is that not all the data that it is possible for a template to display need be constructed beforehand. Thus if sections of the template are hidden or unused, the API can skip calculating data for these sections. In a push style API, all the data that the template could possibly display must be calculated ahead of time and passed to the template before it is rendered.

WACT currently uses a mix of Push and Pull styles. Here is an example of the Pull style with WACT:

<list:LIST name='ExampleList'>
<TABLE BORDER="1" ALIGN="CENTER">
<list:LISTITEM>
<TR><TD>{Name}</TD><TD>{Description}</TD></TR>
</list:LISTITEM>
</TABLE>
</list:LIST>

The corresponding code to bind a database query to this template:

$Page =& new Template('/list.html');
$List =& $Page->findChild('ExampleList');
$List->setDataSet(NewRecordSet('SELECT Name, Description FROM phpmodules'));
$Page->display();

Notice NewRecordSet does not return an array containing all of the records in the database, but instead returns an iterator that the template can use to drive data access. In this example, the data is iterated over only once. If this template fragment is hidden for some reason, there will be no iteration over the data at all.

Additional Information

 
pattern/template_view.txt · Last modified: 2010/08/27 04:52 by hlant
 
Hosting for this site donated by Procata PHP Development