class Template - jcobban/Genealogy GitHub Wiki

class \Templating\Template

Up: PHP Programming Guide

Source Code

Table of Contents:

class \Templating\Template provides the ability to load a model of a document into the server and then customize it by inserting information obtained from the user or from the database. This separates the presentation of information to the client from its internal representation. There are several reasons to do this:

  • The expertise required for doing web presentation is very different from the expertise required to design the application logic of the system. Web presentation should be done by staff who are as close to the end user as possible using tools which facilitate this aspect of development including graphical web page design programs.
  • Different environments may require different styles of presentation. One particular case is support of internationalization. Another is if a web-site is to be embedded within a site which already has a standard presentation.

Template Design

The template file is a valid file following the syntax of a particular format, usually a HypertText Markup Language (HTML), eXtensible Markup Language (XML), or JavaScript Object Notation (JSON) document containing named insertion points. It is particularly important that tags are properly closed in templates, as otherwise template expansion may behave unpredictably. The template engine understands the closure rules for HTML but is not as tolerant of actual violations of HTML syntax as commercial browsers.

Unlike most popular PHP template tools, including PHP itself, Twig, and Blade, this template engine does not incorporate any procedural logic code in the templates. There is complete separation of application logic and page appearance.

Insertion points for text are identified using a notation based upon Perl and PHP (PHP Hypertext Preprocessor) string literal interpolation and have case sensitive names. For example '$MAIN' in a template is replaced by the value of the substitution with name 'MAIN'. If an insertion point is immediately followed by digits or letters or a left square bracket or an object member reference “->” which are not part of the name of the substitution the insertion point can be delimited by using either '${name}' or '{$name}'. For example in the following:

<a href="Census{$censusYear}Details.php?District=$district&SubDistrict=$subDistrict&Division=$division&page=$page">Display Page</a>

the insertion {$censusYear} is marked off with braces so that it is not interpreted as a request to insert the value of 'censusYearDetails'.

If the character before or after the dollar sign is not a left brace “{“ then the name cannot start with a digit or a special character other than underscore, although it can start with any UNICODE character that is not part of ASCII. For example "$15.25" is not interpreted as a request to insert the value of variable "15", and "${}" is not interpreted as a request to insert the value of variable "", but “$Ümłãůt” is interpreted as a request to insert the value assigned to 'Ümłãůt'. To match PHP 7 the “name” can contain an unquoted subscript or a member name reference: for example “$array[1]”, “$array[name]”, or “$object->member”. However a non-numeric subscript should not be enclosed in quotes: for example “$array['name']” is interpreted as the insertion point '$array' followed by literal text “['name']” for consistency with PHP. There is no validation of the contents of anything inside curly braces, for example "{$array*$index}" or “${end-$start}” are accepted by the template engine. However all expressions which are not valid for PHP, are interpreted by the template engine as literal strings to search the set of substitution values. However array and object member references are supported. For example given:

$xmp          = array('1stvalue', '2ndvalue', 'CA' => 'CAvalue');
$obj          = new MyObject;
$obj->field   = 'fieldvalue';
$template->set('XMP',     $xmp);
$template->set('OBJ',     $obj);
  • "$XMP[1]" is replaced by '2ndvalue'
  • "$XMP[CA]" is replaced by 'CAvalue'. Note that there are no quotes in the template.
  • "$OBJ->field" is replaced by 'fieldvalue'

If a dollar sign is not to be interpreted as the beginning of an insertion point but is followed by a character that would make it look like an insertion point, the dollar sign should be escaped: “\$”.

An example of the use of substitutions with subscripts is in the script ReqUpdatePages.php. The template includes a selection for Census:

<select size="9" name="CensusSel" id="CensusSel">
  <option value="" $SELECTED[0]>
     Choose a Census:</option>
 <option value="QC1831" $SELECTED[QC][1831]>
     1831 Quebec</option>
 <option value="CA1851" $SELECTED[CA][1851]>
     1851/52 Canada</option>
 <option value="CA1861" $SELECTED[CA][1861]>
     1861 Canada</option>
 <option value="CA1871" $SELECTED[CA][1871]>
     1871 Canada </option>
 <option value="CA1881" $SELECTED[CA][1881]>
     1881 Canada </option>
  ...
  <option value="CA1921" $SELECTED[CA][1921]>
     1921 Canada </option>
</select> 

The objective is to include selected="selected" on the current option. The application script defines:

$selected	    = array(0	=> ' selected="selected"',
		            'QC'	=> array(1831	=> ''),
		            'CA'	=> array(1851	=> '',
						 1861	=> '',
						 1871	=> '',
						 1881	=> '',
						 ...   			 
					         1921	=> '')
						);
...
    // census has been identified
    $selected[0]           = '';
    $selected['CA',1881]   = 'selected="selected"';
...
$template->set('SELECTED',     $selected);

A specific example of the use of what appears to be an expression within a substitution is in the templates 'CensusResponse...html'. These scripts contain popups which are displayed when the mouse is held over the left and right arrows used for paging through the response. These are customized based upon the type of request and the position within the response, so the template contains:

    <div class="popup" id="mouseprenpprev">
      <p class="label">
	<span id="familyminusonepre">
		Go to Family {$family - 1}}&nbsp;
	</span>
	<span id="pageminusonepre">
		Go to Page {$page - 1}}&nbsp;
	</span>
	<span id="rowminuscountpre">
		Go to Row {$offset - limit + 1}}&nbsp;
	</span>
      </p>
    </div>

This is customized by the script 'CensusResponse.php' as follows:

    if ($family)
    {
	$template['familyminusonepre']->update(array('family - 1'=> ($family - 1)));
	$template['familyplusonepre']->update(array('family + 1'=> ($family + 1)));
	$template['familyminusonepost']->updatearray('family - 1'=> ($family - 1)));
	$template['familyplusonepost']->update(array('family + 1'=> ($family + 1)));
	$template['rowminuscountpre']->update(null);
	$template['rowpluscountpre']->update(null);
	$template['rowminuscountpost']->update(null);
	$template['rowpluscountpost']->update(null);
	$template['pageminusonepre']->update(null);
	$template['pageplusonepre']->update(null);
	$template['pageminusonepost']->update(null);
	$template['pageplusonepost']->update(null);
    }
    else
    ...

The value of the "expression" must be evaluated by the invoking script. It is not evaluated by the template engine.

The application script can insert at each insertion point:

  1. A file, referred to as a sub-template. This supports using a master template that provides a common appearance to pages on the site, plus separate templates from named files for major sub-divisions of the page to customize it for a particular application. This is specified by calling $template‑>includeSub($filename, $insertionpointname). For example the sample template /templates/pageen.html defines a page divided into HTML5 header, main, and footer sections, initializes the contents of the header and footer, and contains an insertion point $MAIN that permits using a sub-template to define the contents of the main section.
  2. A simple text substitution. This is specified by calling:
 $template‑>set($insertionpointname, $string).
  1. An array substitution, where the element of the array is identified in the template. This is specified by calling:
 $template‑>set($insertionpointname, $array).
  1. An object substitution, where the member of the object is identified in the template. This is specified by calling:
 $template‑>set($insertionpointname, $object).

By convention substitution points whose value is assigned by method Template::set or Template::includeSub are identified by all upper-case identifiers. There are special insertion identifiers that the application should not specify:

name contains
MSG If any error messages have been accumulated by the application script in the global variable $msg then that text is included inside a paragraph with class "message" so the distributed styles.css causes the text to be displayed in red.
TRACE If any trace messages have been accumulated by the application script, including trace messages generated by the template processor if debugging is enabled, then these messages are displayed inside a <div class='warning'> so the text is displayed in dark yellow by the distributed styles.css. Note that if the template file does not contain this insertion point, the warning messages generated during the processing of the template are displayed at the end of the output.
TITLE If the script does not define this value it is set to the text contents of the first <h1> tag in the generated page after application of all preceding substitutions. This value is typically displayed by the browser as the title of the window.

Classes derived from class Templating\Template can define further substitutions based upon the environment.

In addition the application script can apply a set of instructions controlling how a specific tag in an HTML or XML document is to be presented. Among other services a tag can be removed, or repeated multiple times with any insertion points within the tag expanded with values specific to each copy. See TemplateTag::update.

This more-powerful substitution mechanism is modeled on JavaScript Document Object Model (DOM) support as used in a browser or in Node.js. This mechanism permits modifying HTML tags which are identified either by the use of the id attribute, or by navigating through the DOM. It not only permits modifying insertion points which are contained within a specific tag, but also creating multiple copies of a tag, or deleting a tag.

A master template file should be used to define the common appearance of all pages on the site. For example it typically specifies the appearance of the header and footer sections of all pages, and identifies the common Cascading Style Sheet which defines the appearance of almost all elements within the site.

If the page requires dynamic functionality that runs in the browser then add one or more <script> tags at the bottom of the file.

    <script src="/jscripts/js20/http.js" type="text/javascript">
    </script>
    <script src="/jscripts/util.js" type="text/javascript">
    </script>
    <script src="/jscripts/scriptname.js" type="text/javascript">
    </script>

It is recommended to include these at the bottom of the file because scripts are acted on when they are encountered as the page is loaded from the server.

  • Placing scripts at the bottom of the template file ensures these scripts have access to the DOM for all of the tags defined in the template file prior to the <script> tag. Otherwise the scripts would have to define a method to be called once the entire DOM is loaded and only examine the DOM from that function.
  • Placing script includes at the bottom also speeds up the presentation of the page because the browser does not have to wait for the scripts to be loaded before starting to display the body of the page.

Alternate Syntax

The template engine supports an alternate syntax for defining insertion points, enclosing them between double braces. In this syntax “{{name}}” has the same behavior as “$name” in the PHP style. The two formats cannot be mixed in the same template file.

Next: class \Genealogy\FtTemplate

⚠️ **GitHub.com Fallback** ⚠️