View Helpers in Zend Framework

April 28, 2008

Tutorials

Views in MVC are allowed to communicate with the Model (using read-only
operations), and are allowed to perform display-related logic. That said,
how do you actually access the model? And what if you have some fairly
complex logic that you may need to repeat, or which you may not want to
display directly in the view in order to keep it clean and easy to read?
In Zend Framework, the answer is to use View Helpers.

What is a View Helper?

A View Helper is simply a class that follows particular naming conventions,
When attached to a view object, you can call the helper as if it were a
method of the view object itself. The View object retains helper instances,
which means that they retain states between calls.

Common use cases for view helpers include:

  • Accessing models
  • Performing complex or repeatable display logic
  • Manipulating and formatting model data
  • Persisting data between view scripts

Creating and Registering a View Helper

The naming conventions are simple. The class must end with the name of the
helper in MixedCase, and contain a method named after the helper using
camelCase. As an example, if we had a helper named ‘FooBar’, we’d need a
class that ended in ‘FooBar’ with a method named ‘fooBar’. View Helper
classes need a class prefix as well; they can’t just be named after
themselves (more on this later). We’ll give our helper the prefix
‘My_Helper’, and it might look like this:

class My_Helper_FooBar
{
    public function fooBar()
    {
    }
}

Following the ZF coding standards, let’s save that in our library as
My/Helper/FooBar.php.

Now we need to register the view helper with the view object.
Zend_View doesn’t allow you to register individual helpers with
it, but you can specify paths to helpers. We’ll do this by calling
the addHelperPath() method, which takes the arguments
$path and $prefix:

$view->addHelperPath('My/Helper/', 'My_Helper');

You can now call this helper as if it were the fooBar() method
of the view object:

$view->fooBar();

Now, what if you need access to the view or other helpers from
within your helper? If you specify a setView() method
in your helper, Zend_View will then inject the current view
object into the helper after instantiating it. Let’s modify our helper to
add this functionality:

class My_Helper_FooBar
{
    public $view;

    public function fooBar()
    {
    }

    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }
}

Now it’s time to ask yourself what the helper should return.
By convention, your helpers should never actually echo any content; they
should return it. Most helpers will do precisely that — returning content.
However, a number of helpers will return instances of themselves — which
allows you to then call additional methods on the helper class. This is
potentially useful when you need to be able to provide state information, or
have a group of related functionality but don’t need or want multiple
helpers to accomplish it. Finally, you may opt to return nothing, and
instead simply perform an operation; one example might be logging page
requests.

In our example, we’ll modify the helper to accept a “name” argument, and
then simply return the string ‘fooBar ‘ plus the name; we’ll escape the name
using the view object’s escaping mechansims. Not terribly helpful, but it
helps illustrate the concept:

class My_Helper_FooBar
{
    public $view;

    public function fooBar($name)
    {
        return 'fooBar ' . $this->view->escape($name);
    }

    public function setView(Zend_View_Interface $view)
    {
        $this->view = $view;
    }
}

Factoids on Helper Paths

Now, a few notes on helper paths and prefixes. First, the path and class
prefix need not have a one-to-one relationship as might your other library
code; what is important, however, is that all classes in that
directory have that class prefix. Zend_View will merely check
to see if a class file with the helper name exists in that directory, and,
if not, move to the next directory in the stack. This means you can group
your helpers in one or more directories, then register these paths with the
view object once — and have access to all helpers in those paths.

Second, we mentioned earlier that you need class prefixes. The reason is to
prevent collisions between libraries and standard class names. This also
allows you to extend existing helpers to provide additional functionality
(e.g., the partialLoop() helper extends partial()).

Third, building on this last point, helper paths, as is the case with all
plugin paths in ZF, operate as style="border-bottom: 1px dotted black">LIFO stacks. This allows
you to create helpers with your own class prefix and have them override
helpers of the same name with different prefixes. In other words, it allows
you to override the behavior of the standard helpers shipped with ZF.

Building on this last point, let’s say you don’t like how the
formHidden() view helper works; you want it to include an extra
class always — so that you can easily pull all hidden elements
using javascript to perform an operation on them. Overall, the base
functionality is fine, so you might do something like this:

class My_View_Helper_FormHidden extends Zend_View_Helper_FormHidden
{
    public function formHidden($name, $value = null, array $attribs = null)
    {
        if (null === $attribs) {
            $attribs = array('class' => 'hidden');
        } else {
            if (array_key_exists('class', $attribs)) {
                $attribs['class'] .= ' hidden';
            } else {
                $attribs['class'] = 'hidden';
            }
        }
        return parent::formHidden($name, $value, $attribs);
    }
}

You could then add a path to this helper to your view object:

$view->addHelperPath('My/View/Helper/', 'My_View_Helper');

and then, any time formHidden() is called, your new helper will
be called.

In summary, helpers are a great way to extend the functionality of
Zend_View — and also a great way to customize and extend other
helpers themselves!

Standard View Helpers

So, now that we’ve covered how to create view helpers and register them with
the view object, you might be wondering what view helpers are available. The
answer is, actually, quite a few.

The standard view helpers shipped with ZF 1.5 fall into roughly three
categories: form helpers, placeholders, and utility helpers:

Form Helpers Placeholders Utility
fieldset()
form()
formButton()
formCheckbox()
formErrors()
formFile()
formHidden()
formImage()
formLabel()
formMultiCheckbox()
formNote()
formPassword()
formRadio()
formReset()
formSelect()
formSubmit()
formText()
formTextarea()
htmlList()
placeholder()
doctype()
headLink()
headMeta()
headScript()
headStyle()
headTitle()
inlineScript()
action()
declareVars()
json()
layout()
partial()
partialLoop()
translate()
url()

I won’t go into what each does; most are self-explanatory, and href="http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial">all
are documented in the manual. However, several of these are worth
mentioning specifically.

Partials

Zend_View has the method render(), which allows
you to render a view script. However, every successive view script rendered
by the view object will have the entire variable scope of the script
preceding it. This can lead to some awkward issues when you want to re-use a
script over multiple iterations, or when you want to manipulate view
variables (which could have consequences for later scripts).

Enter partials. The big difference between rendering a partial and
a normal view script is that a partial gets its own variable scope; it will
only see the variables passed to it directly. As an example, take the
following call to a partial:

<?= $this->partial('foo.phtml', array('foo' => 'bar')) ?>

Were we to call the foo.phtml script normally, it would inherit
all variables in the view. However, calling it as a partial, as above, it
now only receives a single variable, ‘foo’, with the value ‘bar’.

Where might this be useful? One particular case is for looping through
result sets from your model. In fact, this case is so common that an
additional, slightly more performant, helper was created,
partialLoop(). This helper allows you to pass a result set,
over which the helper than iterates, passing the individual result to the
specified partial.

Let’s say we had a Zend_Db_Table_Rowset stored in the
results member of our view. Each item in the rowset is a
Zend_Db_Table_Row; this will be passed to our partial, which
will then be able to use the fields in the row as if they were view
variables. If our table had the fields ‘username’ and ‘email’, we could then
create a partial like the following:

    <li><a href="mailto:<?= $this->escape($this->email) ?>">
        <?= $this->escape($this->username) ?></a></li>

Our view script would then call it in the following context:

<ul>
    <?= $this->partialLoop('results.phtml', $this->results) ?>
</ul>

Partials allow us to operate in a clean scope and separate out useful
tidbits of code for re-use in our applications. Additionally, you end up
with cleaner, more concise application view scripts that contain less
logic and maintain better readability.

Placeholder Helpers

The basic premise around placeholders is persisting content between views.
Within Zend Framework’s MVC, in most cases placeholders do not make sense;
since the same view object is utilized between all controllers and the
layout by default, you can simply utilize view variables as a persistent
storage mechanism. So, why bother with a specific placeholder
implementation?

There are actually several reasons. First off, not everyone uses the same
view object, opting instead to use a separate view object for each discrete
rendering task. Second, and more commonly, developers are using partials –
which have their own variable scope. The only way to persist information
from a view script to a partial will be with a placeholder (or by explicitly
passing the information into the partial). Third, some placeholders are used
to provide defaults and hinting to other helpers — the
doctype() helper is a prime example of this. Finally,
placeholders offer the ability to aggregate and capture content for later
use.

Let’s look at some of these points in more detail.

Doctype

The doctype() helper allows you to specify the HTML DocType for
the final output. This helper is then consulted by many other helpers to
determine how to perform markup; for example, <link> tags do not need
to be closed in HTML4, but in XHTML1, they do. If you wanted to make your
own helper DocType aware, you could then add a check as follows (assuming
you’ve allowed for the view to register itself with the helper):

if ($this->view->doctype()->isXhtml()) {
}

For this to work, however, you have to tell the doctype helper
what DocType is being used before making such calls; otherwise,
they will use the default (which is HTML4 transitional). Add the following
call to your bootstrap or an early-running plugin:

$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->initView();
$viewRenderer->view->doctype('XHTML1_STRICT');

In your layout, simply echo the doctype:

<?= $this->doctype() ?>

Capturing Content

Oftentimes, you need to generate content within an application view
to inject elsewhere in the layout. How can you both generate the content
dynamically and push it into a placeholder?

The answer is simple: placeholders support capturing. So, as an example:

<? $this->placeholder('foo')->captureStart() ?>
Welcome, <a href="/user/profile/<?= $this->userId ?>">
    <?= $this->username ?>
</a>
<? $this->placeholder('foo')->captureEnd() ?>

You can then echo out the placeholder later, and the values will have been
filled in:

<?= $this->placeholder('foo') ?>

While this is useful in and of itself, it’s even more useful when combined
with the following topic: content aggregation.

Content Aggregation

Placeholders actually use a storage container that extends
ArrayObject. This gives them some incredible features and
offers some flexibility that wouldn’t be possible if they were simply stored
as values.

As an example, let’s say you’re building a sidebar for your site, and it
will consist of one or more blocks of content. The sidebar itself needs to
be wrapped in a particular div element, and expects to have
child div elements contained within it. The actual blocks,
however, are dynamic and will be determined by the current user, the page
they are on, and the section of the site they are in.

Since our placeholders are basically glorified arrays, we can actually
append new values into them easily. This allows us to persist the sidebar
between view scripts and then add to it. Additionally, we’ve built in the
ability to specify content with which to surround and separate the items
aggregated in the placeholder.

Let’s setup the basic sidebar defaults:

<? $sidebar = $this->placeholder('sidebar');
   $sidebar->setPrefix('<div id="sidebar"><div class="sidebar-item">')
           ->setSeparator('</div><div class="sidebar-item">')
           ->setPostfix('</div></div>');
?>

What the above does is create a new placeholder, ‘sidebar’. We then set the
text with which to begin the output to be the sidebar div, with a child div
of a sidebar-item. We separate multiple items in the sidebar by closing off
the previous sidebar-item div and starting a new one. Finally, we close the
last child div and the sidebar div.

If you’re a stickler for the presentation of your HTML, you can also
indicate indentation; indentation will be prepended to all items rendered in
the placeholder:

<? $this->placeholder('sidebar')->setIndent('    '); ?>

Note: the above settings can be done any time prior to rendering
the placeholder.

Now, let’s say that we want to display a box showing login status; if the
user is logged in, we display their name; if they are not, we display a
login button. We’ll run this from a plugin that runs at
dispatchLoopStartup():

$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
$viewRenderer->initView();
$view = $viewRenderer->view;

if (Zend_Auth::hasIdentity()) {
    $username = Zend_Auth::getIdentity()->username;
    $content = 'Welcome back, <b>' . $view->escape($username) . '</b>';
} else {
    $content = '<a href="/login">Login</a>';
}
$view->placeholder('sidebar')->append($content);

Our application view script might then want to display a set of links. We’ll
utilize capturing to grab these and set them in the sidebar. By default,
capturing appends to the placeholder, which is exactly what we want to do.

<? $this->placeholder('sidebar')->captureStart() ?>
<ul>
    <li><a href="/foo">Foo</a></li>
    <li><a href="/bar">Bar</a></li>
    <li><a href="/baz">Baz</a></li>
</ul>
<? $this->placeholder('sidebar')->captureEnd() ?>

In our layout script, we can echo the placeholder:

<?= $this->placeholder('sidebar') ?>

Which will generate the following output:

<div id="sidebar"><div class="sidebar-item">
    <a href="/login">Login</a>
</div><div class="sidebar-item">
    <ul>
        <li><a href="/foo">Foo</a></li>
        <li><a href="/bar">Bar</a></li>
        <li><a href="/baz">Baz</a></li>
    </ul>
</div></div>

What if you want to prepend an item to the placeholder? or set it at a
particular index? No problem — use the prepend() or
offsetSet($index, $content) methods. If you want to limit your
placeholder to a single item of content, use the set() method.

Special Placeholder Implementations

There are a number of placeholder implementations contained in the standard
distribution. All of these have the same base functionality as the standard
placeholder() helper, but also extend it. Primarily these are
used for providing information to the layout script in the form of
aggregated <head> content — the page title, scripts, and stylesheets.

For more information on these, you may want to take a look at the following
resources:

  • href="http://weierophinney.net/matthew/archives/163-Using-Zend_View-Placeholders-to-Your-Advantage.html">Using
    Zend_View Placeholders to Your Advantage (disclaimer: I wrote this)
  • href="http://www.zend.com/en/resources/webinars/framework">Zend_Layout
    and Zend_View Enhancements Webinar (look for that title on that page)
  • Zend_Layout and Zend_View Enhancements Demo

Final Word

View Helpers are at heart fairly simple and trivial to implement and utlize.
However, they can add some extremely rich support for your display layer,
help you keep your view scripts clean and manageable, and isolate and
encapsulate often-used logic — allowing you to adhere to the DRY principle.
If you haven’t been using helpers, or if you’ve only been using a subset of
them, give them a try!

And, in case you missed the previous articles:

About Matthew Weier O'Phinney

Matthew is an open source software architect, specializing in PHP. He is currently project lead for Zend Framework, a project with which he has been involved since before the first public preview release. He is a Zend Certified Engineer, and a member of the Zend Education Advisory Board, the group responsible for authoring the Zend Certification Exam. He contributes to a number of open source projects, blogs on PHP-related topics, and presents talks and tutorials related to PHP development and the projects to which he contributes. You can read more of his thoughts on his blog, weierophinney.net/matthew/.

View all posts by Matthew Weier O'Phinney

8 Responses to “View Helpers in Zend Framework”

  1. ryanlball Says:

    Hi, I noticed that I can only access partials when they are in the same (or maybe a sub directory) directory as the layout. Is there a way to change the directory where a partial is read from? Thanks!

  2. kiske Says:

    Hi,

    Is there a way I can use a certain view helper in al my views? Normally you add a helper path in the controller, but is it also possible to do this in a front controller plugin and if yes, how is this done?

  3. debaterdanny Says:

    Thanks – that helps explain this really well.

    One thing for some people to help understand this – it may be obvious but caused me a hiccup – in my bootstrap file I needed to add the document root to the helper path. It wasn’t enough to just say ‘My/Helper/’ but had to add root . ‘My/Helper/’

    thanks again and I look forward to reading your other articles!

  4. weierophinney Says:

    @philip142au: $this is not only not redundant, it’s a
    necessary construct. View scripts are actually executed within the scope of
    the view object — within a method of the view object, to be precise. This
    fact gives the view scripts access to the view object as if it were in the
    local scope — which is how we provide access to the view variables as well
    as helpers. (In fact, this is how we are able to provide a different scope
    to view variables passed into the view script versus view variables defined
    within the view script.)

    Why can we not shorten $this->placeholder() to simply
    placeholder()? Because the latter is a PHP function call, and
    the function does not exist; helpers themselves, if you read the article,
    are classes, with exposed methods. By utilizing the
    $this->placeholder() notation, we can utilize overloading in
    the view object to map the “method” call to a helper class and method. This
    sort of thing is simply not possible with function calls, and would require
    pre-compiling templates or utilizing a stream wrapper to accomplish — both
    of which would significantly impact performance of our view layer.

    That said, there’s nothing saying you couldn’t simply write your
    own Zend_View extension that utilizes a stream wrapper to provide that very
    functionality, if you desire it. We likely will not provide such a wrapper
    within Zend Framework, however.

  5. philip142au Says:

    Hi,

    It feels very redundant to have to use $this-> everywhere.
    $this->placeholder(‘sidebar’)

    Is it really necessary? Why can’t we just placeholder(‘sidebar’)
    Is there a way I could change Zend Framework to work that way?

    Regards, Philip

  6. _____anonymous_____ Says:

    Thanks a lot for your articles and your answer. I think I made a big step in understanding the Zend Framework. Have a good one… mabrin

  7. weierophinney Says:

    Certainly that’s valid. If you look at most MVC diagrams, the View can
    access the model… as long as it does so in a read-only fashion; in other
    words, never alter data from the View. So go for it and create your view
    helpers that access models in order to create widgets for your pages!

    (I myself have a Del.icio.us view helper on my own site that fetches and caches my del.icio.us entries — in this case, Del.icio.us. is my model. I do not post new entries from this widget, I simply list existing entries.)

  8. _____anonymous_____ Says:

    Well, nice articles but I am still a little unsure about my widgets. I have a "top 10 mp3 list"-widget (must access database for live data) which I would like to use in some controller actions.

    After reading this article I would say it must be a View Helper. Is this really the best practice to create a widget with database access as View Helper?

    Thanks, mabrin