Zend_View View Scripts

Zend_View View Scripts: Guide to PHP Template Systems

Understanding Zend_View Instance Properties

Once your controller has assigned variables and called render(), Zend_View includes the requested view script and executes it "inside" the scope of the Zend_View instance. Therefore, in your view scripts, references to $this actually point to the Zend_View instance itself.

Variables assigned to the view from the controller are referred to as instance properties. For example, if the controller were to assign a variable 'something', you would refer to it as $this->something in the view script. This allows you to keep track of which values were assigned to the script, and which are internal to the script itself.

By way of reminder, here is an example view script demonstrating Zend_View variable iteration:


<?php if ($this->books): ?>
<!-- A table of some books. -->
<table>
  <tr>
    <th>Author</th>
    <th>Title</th>
  </tr>
  <?php foreach ($this->books as $key => $val): ?>
  <tr>
    <td><?php echo $this->escape($val['author']) ?></td>
    <td><?php echo $this->escape($val['title']) ?></td>
  </tr>
  <?php endforeach; ?>
</table>
<?php else: ?>
<p>There are no books to display.</p>
<?php endif;?>
    

Escaping Output to Prevent XSS Attacks

One of the most important tasks to perform in a view script is to make sure that output is escaped properly; among other things, this helps to avoid cross-site scripting (XSS) attacks. Unless you are using a function, method, or helper that does escaping on its own, you should always escape variables when you output them.

Zend_View comes with a method called escape() that handles standard HTML entity escaping:


// bad view-script practice:
echo $this->variable;

// good view-script practice:
echo $this->escape($this->variable);
    

By default, the escape() method uses the PHP htmlspecialchars() function for escaping. However, depending on your environment, you may wish for escaping to occur in a different way. Use the setEscape() method at the controller level to tell Zend_View what escaping callback to use.


// create a Zend_View instance
$view = new Zend_View();

// tell it to use htmlentities as the escaping callback
$view->setEscape('htmlentities');

// or tell it to use a static class method as the callback
$view->setEscape(array('SomeClass', 'methodName'));

// or even an instance method
$obj = new SomeClass();
$view->setEscape(array($obj, 'methodName'));

// and then render your view
echo $view->render(...);
    

The callback function or method should take the value to be escaped as its first parameter, and all other parameters should be optional.

Using Alternate Template Systems

Although PHP is itself a powerful template system, many developers feel it is too powerful or complex for their template designers and will want to use an alternate template engine. Zend_View provides two mechanisms for doing so: the first through view scripts, the second by implementing Zend_View_Interface.

Template Systems Using View Scripts

A view script may be used to instantiate and manipulate a separate template object, such as a PHPLIB-style template. The view script for that kind of activity might look something like this:


include_once 'template.inc';
$tpl = new Template();

if ($this->books) {
    $tpl->setFile(array(
        "booklist" => "booklist.tpl",
        "eachbook" => "eachbook.tpl",
    ));

    foreach ($this->books as $key => $val) {
        $tpl->set_var('author', $this->escape($val['author']));
        $tpl->set_var('title', $this->escape($val['title']));
        $tpl->parse("books", "eachbook", true);
    }

    $tpl->pparse("output", "booklist");
} else {
    $tpl->setFile("nobooks", "nobooks.tpl");
    $tpl->pparse("output", "nobooks");
}
      

These would be the related template files:


<!-- booklist.tpl -->
<table>
  <tr>
    <th>Author</th>
    <th>Title</th>
  </tr>
  {books}
</table>

<!-- eachbook.tpl -->
<tr>
  <td>{author}</td>
  <td>{title}</td>
</tr>

<!-- nobooks.tpl -->
<p>There are no books to display.</p>
      

Template Systems Using Zend_View_Interface

Some may find it easier to simply provide a Zend_View-compatible template engine. Zend_View_Interface defines the minimum interface needed for compatibility.

Using this interface, it becomes relatively easy to wrap a third-party template engine as a Zend_View-compatible class. As an example, a wrapper for Smarty could be created, instantiating the Zend_View_Smarty class instead of Zend_View, and then using it in roughly the same fashion as Zend_View:


// Example 1. In initView() of initializer.
$view = new Zend_View_Smarty('/path/to/templates');
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
$viewRenderer->setView($view)
             ->setViewBasePathSpec($view->_smarty->template_dir)
             ->setViewScriptPathSpec(':controller/:action.:suffix')
             ->setViewScriptPathNoControllerSpec(':action.:suffix')
             ->setViewSuffix('tpl');

// Example 2. Initializing view in action controller
class FooController extends Zend_Controller_Action {
    public function init() {
        $this->view = new Zend_View_Smarty('/path/to/templates');
        $viewRenderer = $this->_helper->getHelper('viewRenderer');
        $viewRenderer->setView($this->view)
                     ->setViewBasePathSpec($view->_smarty->template_dir)
                     ->setViewScriptPathSpec(':controller/:action.:suffix')
                     ->setViewScriptPathNoControllerSpec(':action.:suffix')
                     ->setViewSuffix('tpl');
    }
}