View Scripts

Once your controller has assigned variables and called render(), Zend_View then 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 the example view script from the Zend_View introduction.

  1. <?php if ($this->books): ?>
  2.  
  3.     <!-- A table of some books. -->
  4.     <table>
  5.         <tr>
  6.             <th>Author</th>
  7.             <th>Title</th>
  8.         </tr>
  9.  
  10.         <?php foreach ($this->books as $key => $val): ?>
  11.         <tr>
  12.             <td><?php echo $this->escape($val['author']) ?></td>
  13.             <td><?php echo $this->escape($val['title']) ?></td>
  14.         </tr>
  15.         <?php endforeach; ?>
  16.  
  17.     </table>
  18.  
  19. <?php else: ?>
  20.  
  21.     <p>There are no books to display.</p>
  22.  
  23. <?php endif;?>

Escaping Output

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 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 does such escaping for you.

  1. // bad view-script practice:
  2. echo $this->variable;
  3.  
  4. // good view-script practice:
  5. 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.

  1. // create a Zend_View instance
  2. $view = new Zend_View();
  3.  
  4. // tell it to use htmlentities as the escaping callback
  5. $view->setEscape('htmlentities');
  6.  
  7. // or tell it to use a static class method as the callback
  8. $view->setEscape(array('SomeClass', 'methodName'));
  9.  
  10. // or even an instance method
  11. $obj = new SomeClass();
  12. $view->setEscape(array($obj, 'methodName'));
  13.  
  14. // and then render your view
  15. 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:

  1. include_once 'template.inc';
  2. $tpl = new Template();
  3.  
  4. if ($this->books) {
  5.     $tpl->setFile(array(
  6.         "booklist" => "booklist.tpl",
  7.         "eachbook" => "eachbook.tpl",
  8.     ));
  9.  
  10.     foreach ($this->books as $key => $val) {
  11.         $tpl->set_var('author', $this->escape($val['author']);
  12.         $tpl->set_var('title', $this->escape($val['title']);
  13.         $tpl->parse("books", "eachbook", true);
  14.     }
  15.  
  16.     $tpl->pparse("output", "booklist");
  17. } else {
  18.     $tpl->setFile("nobooks", "nobooks.tpl")
  19.     $tpl->pparse("output", "nobooks");
  20. }

These would be the related template files:

  1. <!-- booklist.tpl -->
  2. <table>
  3.     <tr>
  4.         <th>Author</th>
  5.         <th>Title</th>
  6.     </tr>
  7.     {books}
  8. </table>
  9.  
  10. <!-- eachbook.tpl -->
  11.     <tr>
  12.         <td>{author}</td>
  13.         <td>{title}</td>
  14.     </tr>
  15.  
  16. <!-- nobooks.tpl -->
  17. <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 compatability:

  1. /**
  2. * Return the actual template engine object
  3. */
  4. public function getEngine();
  5.  
  6. /**
  7. * Set the path to view scripts/templates
  8. */
  9. public function setScriptPath($path);
  10.  
  11. /**
  12. * Set a base path to all view resources
  13. */
  14. public function setBasePath($path, $prefix = 'Zend_View');
  15.  
  16. /**
  17. * Add an additional base path to view resources
  18. */
  19. public function addBasePath($path, $prefix = 'Zend_View');
  20.  
  21. /**
  22. * Retrieve the current script paths
  23. */
  24. public function getScriptPaths();
  25.  
  26. /**
  27. * Overloading methods for assigning template variables as object
  28. * properties
  29. */
  30. public function __set($key, $value);
  31. public function __isset($key);
  32. public function __unset($key);
  33.  
  34. /**
  35. * Manual assignment of template variables, or ability to assign
  36. * multiple variables en masse.
  37. */
  38. public function assign($spec, $value = null);
  39.  
  40. /**
  41. * Unset all assigned template variables
  42. */
  43. public function clearVars();
  44.  
  45. /**
  46. * Render the template named $name
  47. */
  48. public function render($name);

Using this interface, it becomes relatively easy to wrap a third-party template engine as a Zend_View-compatible class. As an example, the following is one potential wrapper for Smarty:

  1. class Zend_View_Smarty implements Zend_View_Interface
  2. {
  3.     /**
  4.      * Smarty object
  5.      * @var Smarty
  6.      */
  7.     protected $_smarty;
  8.  
  9.     /**
  10.      * Constructor
  11.      *
  12.      * @param string $tmplPath
  13.      * @param array $extraParams
  14.      * @return void
  15.      */
  16.     public function __construct($tmplPath = null, $extraParams = array())
  17.     {
  18.         $this->_smarty = new Smarty;
  19.  
  20.         if (null !== $tmplPath) {
  21.             $this->setScriptPath($tmplPath);
  22.         }
  23.  
  24.         foreach ($extraParams as $key => $value) {
  25.             $this->_smarty->$key = $value;
  26.         }
  27.     }
  28.  
  29.     /**
  30.      * Return the template engine object
  31.      *
  32.      * @return Smarty
  33.      */
  34.     public function getEngine()
  35.     {
  36.         return $this->_smarty;
  37.     }
  38.  
  39.     /**
  40.      * Set the path to the templates
  41.      *
  42.      * @param string $path The directory to set as the path.
  43.      * @return void
  44.      */
  45.     public function setScriptPath($path)
  46.     {
  47.         if (is_readable($path)) {
  48.             $this->_smarty->template_dir = $path;
  49.             return;
  50.         }
  51.  
  52.         throw new Exception('Invalid path provided');
  53.     }
  54.  
  55.     /**
  56.      * Retrieve the current template directory
  57.      *
  58.      * @return string
  59.      */
  60.     public function getScriptPaths()
  61.     {
  62.         return array($this->_smarty->template_dir);
  63.     }
  64.  
  65.     /**
  66.      * Alias for setScriptPath
  67.      *
  68.      * @param string $path
  69.      * @param string $prefix Unused
  70.      * @return void
  71.      */
  72.     public function setBasePath($path, $prefix = 'Zend_View')
  73.     {
  74.         return $this->setScriptPath($path);
  75.     }
  76.  
  77.     /**
  78.      * Alias for setScriptPath
  79.      *
  80.      * @param string $path
  81.      * @param string $prefix Unused
  82.      * @return void
  83.      */
  84.     public function addBasePath($path, $prefix = 'Zend_View')
  85.     {
  86.         return $this->setScriptPath($path);
  87.     }
  88.  
  89.     /**
  90.      * Assign a variable to the template
  91.      *
  92.      * @param string $key The variable name.
  93.      * @param mixed $val The variable value.
  94.      * @return void
  95.      */
  96.     public function __set($key, $val)
  97.     {
  98.         $this->_smarty->assign($key, $val);
  99.     }
  100.  
  101.     /**
  102.      * Allows testing with empty() and isset() to work
  103.      *
  104.      * @param string $key
  105.      * @return boolean
  106.      */
  107.     public function __isset($key)
  108.     {
  109.         return (null !== $this->_smarty->get_template_vars($key));
  110.     }
  111.  
  112.     /**
  113.      * Allows unset() on object properties to work
  114.      *
  115.      * @param string $key
  116.      * @return void
  117.      */
  118.     public function __unset($key)
  119.     {
  120.         $this->_smarty->clear_assign($key);
  121.     }
  122.  
  123.     /**
  124.      * Assign variables to the template
  125.      *
  126.      * Allows setting a specific key to the specified value, OR passing
  127.      * an array of key => value pairs to set en masse.
  128.      *
  129.      * @see __set()
  130.      * @param string|array $spec The assignment strategy to use (key or
  131.      * array of key => value pairs)
  132.      * @param mixed $value (Optional) If assigning a named variable,
  133.      * use this as the value.
  134.      * @return void
  135.      */
  136.     public function assign($spec, $value = null)
  137.     {
  138.         if (is_array($spec)) {
  139.             $this->_smarty->assign($spec);
  140.             return;
  141.         }
  142.  
  143.         $this->_smarty->assign($spec, $value);
  144.     }
  145.  
  146.     /**
  147.      * Clear all assigned variables
  148.      *
  149.      * Clears all variables assigned to Zend_View either via
  150.      * {@link assign()} or property overloading
  151.      * ({@link __get()}/{@link __set()}).
  152.      *
  153.      * @return void
  154.      */
  155.     public function clearVars()
  156.     {
  157.         $this->_smarty->clear_all_assign();
  158.     }
  159.  
  160.     /**
  161.      * Processes a template and returns the output.
  162.      *
  163.      * @param string $name The template to process.
  164.      * @return string The output.
  165.      */
  166.     public function render($name)
  167.     {
  168.         return $this->_smarty->fetch($name);
  169.     }
  170. }

In this example, you would instantiate the Zend_View_Smarty class instead of Zend_View, and then use it in roughly the same fashion as Zend_View:

  1. //Example 1. In initView() of initializer.
  2. $view = new Zend_View_Smarty('/path/to/templates');
  3. $viewRenderer =
  4.     Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer');
  5. $viewRenderer->setView($view)
  6.              ->setViewBasePathSpec($view->_smarty->template_dir)
  7.              ->setViewScriptPathSpec(':controller/:action.:suffix')
  8.              ->setViewScriptPathNoControllerSpec(':action.:suffix')
  9.              ->setViewSuffix('tpl');
  10.  
  11. //Example 2. Usage in action controller remains the same...
  12. class FooController extends Zend_Controller_Action
  13. {
  14.     public function barAction()
  15.     {
  16.         $this->view->book   = 'Zend PHP 5 Certification Study Guide';
  17.         $this->view->author = 'Davey Shafik and Ben Ramsey'
  18.     }
  19. }
  20.  
  21. //Example 3. Initializing view in action controller
  22. class FooController extends Zend_Controller_Action
  23. {
  24.     public function init()
  25.     {
  26.         $this->view   = new Zend_View_Smarty('/path/to/templates');
  27.         $viewRenderer = $this->_helper->getHelper('viewRenderer');
  28.         $viewRenderer->setView($this->view)
  29.                      ->setViewBasePathSpec($view->_smarty->template_dir)
  30.                      ->setViewScriptPathSpec(':controller/:action.:suffix')
  31.                      ->setViewScriptPathNoControllerSpec(':action.:suffix')
  32.                      ->setViewSuffix('tpl');
  33.     }
blog comments powered by Disqus