Templates

A template is a master document used to separate content from presentation. It is often used for mass-production of documents. There is different kinds of templates depending on the type of document it defines. Type of templates include web templates, email templates and LaTeX templates (used to generate PDF files, for example).

A template effectively represents the view in the MVC Architecture. The frame, a component of the controller tier, is responsible for defining the view used to build the reply to the request it received. It is also responsible for sending data taken from the model to the view.

This means the view is only responsible for outputting everything. As opposed to other implementations of the MVC design pattern, the view does not have to retrieve data, the view actually expects that all data it requires has been provided to it. Missing data will produce an error page.

Usage

If you are using the application module, please refer to this chapter.

If you are not using the application framework, you can create a template simply by creating an instance.

<?php

$oTemplate = new weeTemplate('myexample');

This will load the file app/tpl/myexample.tpl.

You can change the default template path (app/tpl) by defining the TPL_PATH constant. Similarly, you can change the template extension (.tpl) by defining the TPL_EXT constant in your bootstrap file.

Sending data to the template is really simple. It works exactly the same whether you use the application module or not. You just need to call the set method.

<?php

// Using $oTemplate created previously

$oTemplate->set('name', 'World');
$oTemplate->set('items', array('earth', 'moon', 'mars'));

Same example with the application module. The set method of weeFrame simply redirects the data to the template. The frame will not create the template until required. This means that the first call to set will effectively create the template object. If you don't use set the template will be created before it must be rendered. In some cases, for example when sending a taconite reply in an xmlhttprequest context, the template might not be created at all, saving resources.

<?php

class myExample extends weeFrame
{
	// No need to specify the template: it is the name of the class by default
	// In other words it is set to 'mytemplate' here

	protected function defaultEvent($aEvent)
	{
		$this->set('name', 'World');
		$this->set('items', array('earth', 'moon', 'mars'));
	}
}

You may prefer to use an alternative syntax for the set method, allowing to pass more variables in the same call. Simply give an array as a single parameter instead of two.

<?php

class myExample extends weeFrame
{
	protected function defaultEvent($aEvent)
	{
		$this->set(array(
			'name'  => 'World',
			'items' => array('earth', 'moon', 'mars'),
		));
	}
}

There is no need to encode the data passed to the template using the set method. All data is encoded automatically according to the output driver you selected. You must however encode data if it is not processed by the set method. You must also encode data passed using the set method as an object that doesn't extend the weeDataSource class. The best way to write secure template is to write them completely standalone, requiring only input from the set method.

These three examples result in exactly the same data passed to the template. On the template's side, this effectively creates variables using the names and values your provided. You can then output them as needed.

<html>
<head>
	<title>Testing Templates</title>
</head>

<body>
	<p>Hello, <?php echo $name?>!</p>

	<ul>
		<?php foreach ($items as $item):?> 
			<li><?php echo $item?></li>
		<?php endforeach?> 
	</ul>
</body>
</html>

You should use the alternative syntax for control structures in your templates. It is the easier syntax to read, as was demonstrated here.

Note that PHP has a tendency to remove the line break immediately following ?>, resulting in a badly formatted file. Although white spaces do not really matter when dealing with XHTML, it becomes a problem if you're outputting other formats like plain text. This problem can be resolved by appending a space after ?>. It is good practice to always put a space after all the ?> that are followed by a line break.

A template can include another template. A common use of this functionality is to separate the header and the footer of the page into their own templates. Here is an example such template file:

<?php $this->template('header', array('title' => 'Included Template'))?> 

<div id="contents">
	Insert contents of the page here.
</div>

<?php $this->template('footer')?> 

We can do this because we are actually executing code in the weeTemplate class. You could call any of its methods if you wanted to. Note however that it is neither safe nor a good practice to call a method other than template and mkLink (detailed below).

The nested template will receive all the data that has been submitted to the main template. You can also send additional data by specifying it in an array given as a second parameter to the template method.

Safe link generation

weeTemplate contain methods that can be used to build links. The links can be pre-parameterized, allowing you to specify in advance a number of variables that will be appended to all the links built using the template's method.

To add parameters to the links, simply call addLinkArgs:

<?php

$oTemplate->addLinkArgs(array(
	'location'	=> $oUser->getLocation(),
	'year'		=> $oUser->getYearActive(),
));

Then, if you call mkLink from within the template, a correct link containing these two parameters will be built. Make sure the link you give is not HTML encoded; in other words you need to decode it if you passed it to the template from within the frame.

Normal: <a href="<?php echo APP_PATH?>user/viewlogs?location=<?php echo $location?>&amp;year=<?php echo $year?>">view logs</a>
MkLink: <a href="<?php echo $this->mkLink(APP_PATH . 'user/viewlogs')?>">view logs</a>

You can pass additional parameters to the method that will be appended only for this link.

Normal: <a href="<?php echo APP_PATH?>user/viewlogs?location=<?php echo $location?>&amp;year=<?php echo $year?>&amp;deleted=<?php echo $deleted?>">view deleted logs</a>
MkLink: <a href="<?php echo $this->mkLink('user/viewlogs', array('deleted', $deleted))?>">view deleted logs</a>

As you can see, this can save you a lot of typing if all your links must contain the same parameters.

Note that there is currently no proxy method in weeFrame to add parameters to links using addLinkArgs. Unfortunately, this means you'll have to write a few more lines to ensure it works as intended. This will be fixed before going stable.

You have to ensure the template is created before calling the method. This can be achieved by using the following code:

<?php

class myFrame extends weeFrame
{
	// ...

	public function defaultEvent($aEvent)
	{
		if (empty($this->oTpl))
			$this->loadTemplate();

		$this->oTpl->addLinkArgs(array(
			'location' => $oUser->getLocation(),
			'year'     => $oUser->getYearActive(),
		));
	}
}

Using this event in a frame will send the correct link parameters to the template, making all links created with mkLink contain a location and year parameter.

Rendering

If you are using the application module you do not need to render templates yourself. In other cases, a template can be easily rendered by using the method render.

<?php

echo $oTemplate->render();

You can also retrieve the output of a template by calling the method toString. You can then process it as you wish. The following example will replace all example by demo in the resulting string and then output it.

<?php

echo str_replace('example', 'demo', $oTemplate->toString());