Custom View Helpers in Zend Framework

The Zend Framework Manual describes View Helpers like so:

> "In your view scripts, often it is necessary to perform certain complex functions over and over; e.g., formatting a date, generating form elements, or displaying action links. You can use helper classes to perform these behaviors for you."

Currently the framework (version 0.1.3) includes a small selection of form helpers which will no doubt expand as it matures. For now I'm more interested in the ability to add custom helpers for specific project use. The first thing I did was to set up the same directory structure as ZendViewHelper as is suggested when subclassing controllers:

library/
    Zend/
        View/
            Helper/
    MyProject/
        View/
            Helper/

Having my project specific helper files in library/MyProject/View/Helper/ will make it easy to keep them separate from Zend core updates.

The next step is to tell ZendView to look in the custom helper directory as well as the default Zend helper directory. This just requires adding the new helper path to the ZendView object I created in the public_html/index.php file:

$view = new Zend_View;
$view->addHelperPath('MyProject/View/Helper');

Cautionary Note (* see update below)

The above is actually a bit of a fiddle to get working if you decide like I did to use a relative path to your helper files. I had set...

set_include_path( /home/exciting_zfw_site/library/ );

...pointing to the main Zend library directory, however, ZendViewAbstract:: loadClass() uses isreadable() as a check before loading any helper or filter files like so...

if (is_readable($dir . $file)) { include $dir . $file;

if (! classexists($class, false)) { $msg = "$type '$name' loaded but class '$class' not found within"; throw new ZendView_Exception($msg); }

return $class; }

...and since is_readable just ignores include paths, your new helper files won't be found. This is currently listed as a bug but for the moment I simply changed...

if (is_readable($dir . $file)) { include $dir . $file;

...to...

if (include $dir . $file) {

...and it worked fine. Portability was the reason I wanted to keep the paths relative as I move files from a development server to the live server. It's much easier to keep as few path configuration settings as possible.

The next step is pretty well documented in the manual but for the sake of completeness I'll keep going. Create a new helper file:

class ZendViewHelper_DoStuff {

public function doStuff() { return 'Hello to you all'; } }

Another Cautionary Note

Something that caught me out was that the new helper class must be called ZendViewHelperYourNameHere rather than MyProjectViewHelperYourNameHere which seems a little odd considering it's position in the directory structure I mentioned before. While logically it is a Zend_View helper class, it will be kept with other subclassed files with your own "namespaced" class names under the MyProject directory so it seems to break a convention.

Ready to use

After saving the new helper file in MyProject/View/Helper/DoStuff.php it should be available to use in your view scripts like so:

doStuff(); ?>

When writing helper classes the key points to initially getting them to work are the naming conventions as illustrated by my doStuff example:

  1. Class name must be ZendViewHelper_DoStuff
  2. The class must contain a public function doStuff()
  3. The file must be save as DoStuff.php

As mentioned in my post on getting to know Zend_View elements of the above may well change as development continues.

Further Reading

View Helpers in the Zend Framework Manual

* Update

Forget the above hack...

if (include $dir . $file) {

...as it will produce warnings as ZendViewAbstract::_LoadClass() attempts to include the doStuff file from any other path in the _path stack. Instead the only solution I've found to currently work is to specify a relative path like so:

$view->addHelperPath('../MyProject/UW/View/Helper');