View Helpers
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, or plugin, classes to perform these
behaviors for you.
A helper is simply a class that implements the interface Zend\View\Helper. Helper simply defines two
methods, setView(), which accepts a Zend\View\Renderer instance/implementation, and getView(), used to
retrieve that instance. Zend\View\PhpRenderer composes a plugin broker,
allowing you to retrieve helpers, and also provides some method overloading capabilities that allow proxying method
calls to helpers.
As an example, let’s say we have a helper class named My\Helper\LowerCase, which we map in our plugin broker to
the name “lowercase”. We can retrieve or invoke it in one of the following ways:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | // $view is a PhpRenderer instance
// Via the plugin broker:
$broker = $view->getBroker();
$helper = $broker->load('lowercase');
// Retrieve the helper instance, via the method "plugin",
// which proxies to the plugin broker:
$helper = $view->plugin('lowercase');
// If the helper does not define __invoke(), the following also retrieves it:
$helper = $view->lowercase();
// If the helper DOES define __invoke, you can call the helper
// as if it is a method:
$filtered = $view->lowercase('some value');
|
The last two examples demonstrate how the PhpRenderer uses method overloading to retrieve and/or invoke helpers
directly, offering a convenience API for end users.
A large number of helpers are provided in the standard distribution of Zend Framework. You can also register
helpers by adding them to the plugin broker, or the plugin locator the broker
composes. Please refer to the plugin broker documentation for details.
Included Helpers
Zend Framework comes with an initial set of helper classes. In particular, there are helpers for creating
route-based URLs and HTML lists, as well as declaring variables. Additionally, there are a rich set of
helpers for providing values for, and rendering, the various HTML <head> tags, such as HeadTitle,
HeadLink, and HeadScript. The currently shipped helpers include:
- url($name, $urlParams, $routeOptions, $reuseMatchedParams): Creates a URL string based on a named route. $urlParams should be an
associative array of key/value pairs used by the particular route.
- htmlList($items, $ordered, $attribs, $escape): generates unordered and ordered lists based on the $items
passed to it. If $items is a multidimensional array, a nested list will be built. If the $escape flag is
TRUE (default), individual items will be escaped using the view objects registered escaping mechanisms; pass
a FALSE value if you want to allow markup in your lists.
BaseUrl Helper
While most URLs generated by the framework have the base URL prepended automatically, developers will need to
prepend the base URL to their own URLs in order for paths to resources to be correct.
Usage of the BaseUrl helper is very straightforward:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | /*
* The following assume that the base URL of the page/application is "/mypage".
*/
/*
* Prints:
* <base href="/mypage/" />
*/
<base href="<?php echo $this->baseUrl(); ?>" />
/*
* Prints:
* <link rel="stylesheet" type="text/css" href="/mypage/css/base.css" />
*/
<link rel="stylesheet" type="text/css"
href="<?php echo $this->baseUrl('css/base.css'); ?>" />
|
Note
For simplicity’s sake, we strip out the entry PHP file (e.g., “index.php”) from the base URL that was
contained in Zend_Controller. However, in some situations this may cause a problem. If one occurs, use
$this->getHelper('BaseUrl')->setBaseUrl() to set your own BaseUrl.
Cycle Helper
The Cycle helper is used to alternate a set of values.
Cycle Helper Basic Usage
To add elements to cycle just specify them in constructor or use assign(array $data) function
1
2
3
4
5
6
7
8
9
10
11
12 | <?php foreach ($this->books as $book):?>
<tr style="background-color:<?php echo $this->cycle(array("#F0F0F0",
"#FFFFFF"))
->next()?>">
<td><?php echo $this->escapeHtml($book['author']) ?></td>
</tr>
<?php endforeach;?>
// Moving in backwards order and assign function
$this->cycle()->assign(array("#F0F0F0","#FFFFFF"));
$this->cycle()->prev();
?>
|
The output
| <tr style="background-color:'#F0F0F0'">
<td>First</td>
</tr>
<tr style="background-color:'#FFFFFF'">
<td>Second</td>
</tr>
|
Working with two or more cycles
To use two cycles you have to specify the names of cycles. Just set second parameter in cycle method.
$this->cycle(array("#F0F0F0","#FFFFFF"),'cycle2'). You can also use setName($name) function.
| <?php foreach ($this->books as $book):?>
<tr style="background-color:<?php echo $this->cycle(array("#F0F0F0",
"#FFFFFF"))
->next()?>">
<td><?php echo $this->cycle(array(1,2,3),'number')->next()?></td>
<td><?php echo $this->escapeHtml($book['author'])?></td>
</tr>
<?php endforeach;?>
|
Partial Helper
The Partial view helper is used to render a specified template within its own variable scope. The primary use
is for reusable template fragments with which you do not need to worry about variable name clashes. Additionally,
they allow you to specify partial view scripts from specific modules.
A sibling to the Partial, the PartialLoop view helper allows you to pass iterable data, and render a
partial for each item.
Note
PartialLoop Counter
The PartialLoop view helper assigns a variable to the view named partialCounter which passes the current
position of the array to the view script. This provides an easy way to have alternating colors on table rows for
example.
Basic Usage of Partials
Basic usage of partials is to render a template fragment in its own view scope. Consider the following partial
script:
| <?php // partial.phtml ?>
<ul>
<li>From: <?php echo $this->escapeHtml($this->from) ?></li>
<li>Subject: <?php echo $this->escapeHtml($this->subject) ?></li>
</ul>
|
You would then call it from your view script using the following:
| <?php echo $this->partial('partial.phtml', array(
'from' => 'Team Framework',
'subject' => 'view partials')); ?>
|
Which would then render:
| <ul>
<li>From: Team Framework</li>
<li>Subject: view partials</li>
</ul>
|
Note
What is a model?
A model used with the Partial view helper can be one of the following:
- Array. If an array is passed, it should be associative, as its key/value pairs are assigned to the view
with keys as view variables.
- Object implementing toArray() method. If an object is passed an has a toArray() method, the results of
toArray() will be assigned to the view object as view variables.
- Standard object. Any other object will assign the results of object_get_vars() (essentially all public
properties of the object) to the view object.
If your model is an object, you may want to have it passed as an object to the partial script, instead of
serializing it to an array of variables. You can do this by setting the ‘objectKey’ property of the appropriate
helper:
| // Tell partial to pass objects as 'model' variable
$view->partial()->setObjectKey('model');
// Tell partial to pass objects from partialLoop as 'model' variable
// in final partial view script:
$view->partialLoop()->setObjectKey('model');
|
This technique is particularly useful when passing Zend_Db_Table_Rowsets to partialLoop(), as you then
have full access to your row objects within the view scripts, allowing you to call methods on them (such as
retrieving values from parent or dependent rows).
Using PartialLoop to Render Iterable Models
Typically, you’ll want to use partials in a loop, to render the same content fragment many times; this way you can
put large blocks of repeated content or complex display logic into a single location. However this has a
performance impact, as the partial helper needs to be invoked once for each iteration.
The PartialLoop view helper helps solve this issue. It allows you to pass an iterable item (array or object
implementing Iterator) as the model. It then iterates over this, passing, the items to the partial script as
the model. Items in the iterator may be any model the Partial view helper allows.
Let’s assume the following partial view script:
| <?php // partialLoop.phtml ?>
<dt><?php echo $this->key ?></dt>
<dd><?php echo $this->value ?></dd>
|
And the following “model”:
| $model = array(
array('key' => 'Mammal', 'value' => 'Camel'),
array('key' => 'Bird', 'value' => 'Penguin'),
array('key' => 'Reptile', 'value' => 'Asp'),
array('key' => 'Fish', 'value' => 'Flounder'),
);
|
In your view script, you could then invoke the PartialLoop helper:
| <dl>
<?php echo $this->partialLoop('partialLoop.phtml', $model) ?>
</dl>
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | <dl>
<dt>Mammal</dt>
<dd>Camel</dd>
<dt>Bird</dt>
<dd>Penguin</dd>
<dt>Reptile</dt>
<dd>Asp</dd>
<dt>Fish</dt>
<dd>Flounder</dd>
</dl>
|
Rendering Partials in Other Modules
Sometime a partial will exist in a different module. If you know the name of the module, you can pass it as the
second argument to either partial() or partialLoop(), moving the $model argument to third position.
For instance, if there’s a pager partial you wish to use that’s in the ‘list’ module, you could grab it as follows:
| <?php echo $this->partial('pager.phtml', 'list', $pagerData) ?>
|
In this way, you can re-use partials created specifically for other modules. That said, it’s likely a better
practice to put re-usable partials in shared view script paths.
Placeholder Helper
The Placeholder view helper is used to persist content between view scripts and view instances. It also offers
some useful features such as aggregating content, capturing view script content for later use, and adding pre- and
post-text to content (and custom separators for aggregated content).
Basic Usage of Placeholders
Basic usage of placeholders is to persist view data. Each invocation of the Placeholder helper expects a
placeholder name; the helper then returns a placeholder container object that you can either manipulate or simply
echo out.
| <?php $this->placeholder('foo')->set("Some text for later") ?>
<?php
echo $this->placeholder('foo');
// outputs "Some text for later"
?>
|
Using Placeholders to Aggregate Content
Aggregating content via placeholders can be useful at times as well. For instance, your view script may have a
variable array from which you wish to retrieve messages to display later; a later view script can then determine
how those will be rendered.
The Placeholder view helper uses containers that extend ArrayObject, providing a rich featureset for
manipulating arrays. In addition, it offers a variety of methods for formatting the content stored in the
container:
- setPrefix($prefix) sets text with which to prefix the content. Use getPrefix() at any time to determine
what the current setting is.
- setPostfix($prefix) sets text with which to append the content. Use getPostfix() at any time to determine
what the current setting is.
- setSeparator($prefix) sets text with which to separate aggregated content. Use getSeparator() at any time
to determine what the current setting is.
- setIndent($prefix) can be used to set an indentation value for content. If an integer is passed, that number
of spaces will be used; if a string is passed, the string will be used. Use getIndent() at any time to
determine what the current setting is.
| <!-- first view script -->
<?php $this->placeholder('foo')->exchangeArray($this->data) ?>
|
1
2
3
4
5
6
7
8
9
10
11
12 | <!-- later view script -->
<?php
$this->placeholder('foo')->setPrefix("<ul>\n <li>")
->setSeparator("</li><li>\n")
->setIndent(4)
->setPostfix("</li></ul>\n");
?>
<?php
echo $this->placeholder('foo');
// outputs as unordered list with pretty indentation
?>
|
Because the Placeholder container objects extend ArrayObject, you can also assign content to a specific key
in the container easily, instead of simply pushing it into the container. Keys may be accessed either as object
properties or as array keys.
| <?php $this->placeholder('foo')->bar = $this->data ?>
<?php echo $this->placeholder('foo')->bar ?>
<?php
$foo = $this->placeholder('foo');
echo $foo['bar'];
?>
|
Using Placeholders to Capture Content
Occasionally you may have content for a placeholder in a view script that is easiest to template; the
Placeholder view helper allows you to capture arbitrary content for later rendering using the following API.
captureStart($type, $key) begins capturing content.
$type should be one of the Placeholder constants APPEND or SET. If APPEND, captured content
is appended to the list of current content in the placeholder; if SET, captured content is used as the sole
value of the placeholder (potentially replacing any previous content). By default, $type is APPEND.
$key can be used to specify a specific key in the placeholder container to which you want content captured.
captureStart() locks capturing until captureEnd() is called; you cannot nest capturing with the same
placeholder container. Doing so will raise an exception.
captureEnd() stops capturing content, and places it in the container object according to how
captureStart() was called.
| <!-- Default capture: append -->
<?php $this->placeholder('foo')->captureStart();
foreach ($this->data as $datum): ?>
<div class="foo">
<h2><?php echo $datum->title ?></h2>
<p><?php echo $datum->content ?></p>
</div>
<?php endforeach; ?>
<?php $this->placeholder('foo')->captureEnd() ?>
<?php echo $this->placeholder('foo') ?>
|
| <!-- Capture to key -->
<?php $this->placeholder('foo')->captureStart('SET', 'data');
foreach ($this->data as $datum): ?>
<div class="foo">
<h2><?php echo $datum->title ?></h2>
<p><?php echo $datum->content ?></p>
</div>
<?php endforeach; ?>
<?php $this->placeholder('foo')->captureEnd() ?>
<?php echo $this->placeholder('foo')->data ?>
|
Concrete Placeholder Implementations
Zend Framework ships with a number of “concrete” placeholder implementations. These are for commonly used
placeholders: doctype, page title, and various <head> elements. In all cases, calling the placeholder with no
arguments returns the element itself.
Documentation for each element is covered separately, as linked below:
Doctype Helper
Valid HTML and XHTML documents should include a DOCTYPE declaration. Besides being difficult to remember,
these can also affect how certain elements in your document should be rendered (for instance, CDATA escaping in
<script> and <style> elements.
The Doctype helper allows you to specify one of the following types:
- XHTML11
- XHTML1_STRICT
- XHTML1_TRANSITIONAL
- XHTML1_FRAMESET
- XHTML1_RDFA
- XHTML_BASIC1
- HTML4_STRICT
- HTML4_LOOSE
- HTML4_FRAMESET
- HTML5
You can also specify a custom doctype as long as it is well-formed.
The Doctype helper is a concrete implementation of the Placeholder helper.
Doctype Helper Basic Usage
You may specify the doctype at any time. However, helpers that depend on the doctype for their output will
recognize it only after you have set it, so the easiest approach is to specify it in your bootstrap:
| $doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_STRICT');
|
And then print it out on top of your layout script:
| <?php echo $this->doctype() ?>
|
Retrieving the Doctype
If you need to know the doctype, you can do so by calling getDoctype() on the object, which is returned by
invoking the helper.
| $doctype = $view->doctype()->getDoctype();
|
Typically, you’ll simply want to know if the doctype is XHTML or not; for this, the isXhtml() method will
suffice:
| if ($view->doctype()->isXhtml()) {
// do something differently
}
|
You can also check if the doctype represents an HTML5 document.
| if ($view->doctype()->isHtml5()) {
// do something differently
}
|
Choosing a Doctype to Use with the Open Graph Protocol
To implement the Open Graph Protocol, you may specify the XHTML1_RDFA doctype. This doctype allows a developer
to use the Resource Description Framework within an XHTML document.
| $doctypeHelper = new Zend_View_Helper_Doctype();
$doctypeHelper->doctype('XHTML1_RDFA');
|
The RDFa doctype allows XHTML to validate when the ‘property’ meta tag attribute is used per the Open Graph
Protocol spec. Example within a view script:
| <?php echo $this->doctype('XHTML1_RDFA'); ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:og="http://opengraphprotocol.org/schema/">
<head>
<meta property="og:type" content="musician" />
|
In the previous example, we set the property to og:type. The og references the Open Graph namespace we specified in
the html tag. The content identifies the page as being about a musician. See the Open Graph Protocol
documentation for supported properties. The HeadMeta helper may be
used to programmatically set these Open Graph Protocol meta tags.
Here is how you check if the doctype is set to XHTML1_RDFA:
| <?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml"
<?php if ($view->doctype()->isRdfa()): ?>
xmlns:og="http://opengraphprotocol.org/schema/"
xmlns:fb="http://www.facebook.com/2008/fbml"
<?php endif; ?>
>
|
HeadLink Helper
The HTML <link> element is increasingly used for linking a variety of resources for your site: stylesheets,
feeds, favicons, trackbacks, and more. The HeadLink helper provides a simple interface for creating and
aggregating these elements for later retrieval and output in your layout script.
The HeadLink helper has special methods for adding stylesheet links to its stack:
- appendStylesheet($href, $media, $conditionalStylesheet, $extras)
- offsetSetStylesheet($index, $href, $media, $conditionalStylesheet, $extras)
- prependStylesheet($href, $media, $conditionalStylesheet, $extras)
- setStylesheet($href, $media, $conditionalStylesheet, $extras)
The $media value defaults to ‘screen’, but may be any valid media value. $conditionalStylesheet is a string
or boolean FALSE, and will be used at rendering time to determine if special comments should be included to
prevent loading of the stylesheet on certain platforms. $extras is an array of any extra values that you want
to be added to the tag.
Additionally, the HeadLink helper has special methods for adding ‘alternate’ links to its stack:
- appendAlternate($href, $type, $title, $extras)
- offsetSetAlternate($index, $href, $type, $title, $extras)
- prependAlternate($href, $type, $title, $extras)
- setAlternate($href, $type, $title, $extras)
The headLink() helper method allows specifying all attributes necessary for a <link> element, and allows
you to also specify placement – whether the new element replaces all others, prepends (top of stack), or appends
(end of stack).
The HeadLink helper is a concrete implementation of the Placeholder helper.
HeadLink Helper Basic Usage
You may specify a headLink at any time. Typically, you will specify global links in your layout script, and
application specific links in your application view scripts. In your layout script, in the <head> section, you will
then echo the helper to output it.
1
2
3
4
5
6
7
8
9
10
11
12 | <?php // setting links in a view script:
$this->headLink()->appendStylesheet('/styles/basic.css')
->headLink(array('rel' => 'icon',
'href' => '/img/favicon.ico'),
'PREPEND')
->prependStylesheet('/styles/moz.css',
'screen',
true,
array('id' => 'my_stylesheet'));
?>
<?php // rendering the links: ?>
<?php echo $this->headLink() ?>
|
HeadMeta Helper
The HTML <meta> element is used to provide meta information about your HTML document – typically keywords,
document character set, caching pragmas, etc. Meta tags may be either of the ‘http-equiv’ or ‘name’ types, must
contain a ‘content’ attribute, and can also have either of the ‘lang’ or ‘scheme’ modifier attributes.
The HeadMeta helper supports the following methods for setting and adding meta tags:
- appendName($keyValue, $content, $conditionalName)
- offsetSetName($index, $keyValue, $content, $conditionalName)
- prependName($keyValue, $content, $conditionalName)
- setName($keyValue, $content, $modifiers)
- appendHttpEquiv($keyValue, $content, $conditionalHttpEquiv)
- offsetSetHttpEquiv($index, $keyValue, $content, $conditionalHttpEquiv)
- prependHttpEquiv($keyValue, $content, $conditionalHttpEquiv)
- setHttpEquiv($keyValue, $content, $modifiers)
- setCharset($charset)
The following methods are also supported with XHTML1_RDFA doctype set with the Doctype helper:
- appendProperty($property, $content, $modifiers)
- offsetSetProperty($index, $property, $content, $modifiers)
- prependProperty($property, $content, $modifiers)
- setProperty($property, $content, $modifiers)
The $keyValue item is used to define a value for the ‘name’ or ‘http-equiv’ key; $content is the value for
the ‘content’ key, and $modifiers is an optional associative array that can contain keys for ‘lang’ and/or
‘scheme’.
You may also set meta tags using the headMeta() helper method, which has the following signature:
headMeta($content, $keyValue, $keyType = 'name', $modifiers = array(), $placement = 'APPEND'). $keyValue is
the content for the key specified in $keyType, which should be either ‘name’ or ‘http-equiv’. $keyType may
also be specified as ‘property’ if the doctype has been set to XHTML1_RDFA. $placement can be ‘SET’ (overwrites
all previously stored values), ‘APPEND’ (added to end of stack), or ‘PREPEND’ (added to top of stack).
HeadMeta overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the
special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes
using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally
modify these items by simply modifying the object returned.
The HeadMeta helper is a concrete implementation of the Placeholder helper.
HeadMeta Helper Basic Usage
You may specify a new meta tag at any time. Typically, you will specify client-side caching rules or SEO keywords.
For instance, if you wish to specify SEO keywords, you’d be creating a meta name tag with the name ‘keywords’ and
the content the keywords you wish to associate with your page:
| // setting meta keywords
$this->headMeta()->appendName('keywords', 'framework, PHP, productivity');
|
If you wished to set some client-side caching rules, you’d set http-equiv tags with the rules you wish to enforce:
| // disabling client-side cache
$this->headMeta()->appendHttpEquiv('expires',
'Wed, 26 Feb 1997 08:21:57 GMT')
->appendHttpEquiv('pragma', 'no-cache')
->appendHttpEquiv('Cache-Control', 'no-cache');
|
Another popular use for meta tags is setting the content type, character set, and language:
| // setting content type and character set
$this->headMeta()->appendHttpEquiv('Content-Type',
'text/html; charset=UTF-8')
->appendHttpEquiv('Content-Language', 'en-US');
|
If you are serving an HTML5 document, you should provide the character set like this:
| // setting character set in HTML5
$this->headMeta()->setCharset('UTF-8'); // Will look like <meta charset="UTF-8">
|
As a final example, an easy way to display a transitional message before a redirect is using a “meta refresh”:
| // setting a meta refresh for 3 seconds to a new url:
$this->headMeta()->appendHttpEquiv('Refresh',
'3;URL=http://www.some.org/some.html');
|
When you’re ready to place your meta tags in the layout, simply echo the helper:
| <?php echo $this->headMeta() ?>
|
HeadMeta Usage with XHTML1_RDFA doctype
Enabling the RDFa doctype with the Doctype helper enables the use of the
‘property’ attribute (in addition to the standard ‘name’ and ‘http-equiv’) with HeadMeta. This is commonly used
with the Facebook Open Graph Protocol.
For instance, you may specify an open graph page title and type as follows:
| $this->doctype(Zend_View_Helper_Doctype::XHTML_RDFA);
$this->headMeta()->setProperty('og:title', 'my article title');
$this->headMeta()->setProperty('og:type', 'article');
echo $this->headMeta();
// output is:
// <meta property="og:title" content="my article title" />
// <meta property="og:type" content="article" />
|
HeadScript Helper
The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote
resource containing client-side scripting code. The HeadScript helper allows you to manage both.
The HeadScript helper supports the following methods for setting and adding scripts:
- appendFile($src, $type = 'text/javascript', $attrs = array())
- offsetSetFile($index, $src, $type = 'text/javascript', $attrs = array())
- prependFile($src, $type = 'text/javascript', $attrs = array())
- setFile($src, $type = 'text/javascript', $attrs = array())
- appendScript($script, $type = 'text/javascript', $attrs = array())
- offsetSetScript($index, $script, $type = 'text/javascript', $attrs = array())
- prependScript($script, $type = 'text/javascript', $attrs = array())
- setScript($script, $type = 'text/javascript', $attrs = array())
In the case of the * File() methods, $src is the remote location of the script to load; this is usually in
the form of a URL or a path. For the * Script() methods, $script is the client-side scripting directives
you wish to use in the element.
Note
Setting Conditional Comments
HeadScript allows you to wrap the script tag in conditional comments, which allows you to hide it from
specific browsers. To add the conditional tags, pass the conditional value as part of the $attrs parameter
in the method calls.
Headscript With Conditional Comments
| // adding scripts
$this->headScript()->appendFile(
'/js/prototype.js',
'text/javascript',
array('conditional' => 'lt IE 7')
);
|
Note
Preventing HTML style comments or CDATA wrapping of scripts
By default HeadScript will wrap scripts with HTML comments or it wraps scripts with XHTML cdata. This
behavior can be problematic when you intend to use the script tag in an alternative way by setting the type to
something other then ‘text/javascript’. To prevent such escaping, pass an noescape with a value of true as
part of the $attrs parameter in the method calls.
Create an jQuery template with the headScript
| // jquery template
$template = '<div class="book">{{:title}}</div>';
$this->headScript()->appendScript(
$template,
'text/x-jquery-tmpl',
array('id='tmpl-book', 'noescape' => true)
);
|
HeadScript also allows capturing scripts; this can be useful if you want to create the client-side script
programmatically, and then place it elsewhere. The usage for this will be showed in an example below.
Finally, you can also use the headScript() method to quickly add script elements; the signature for this is
headScript($mode = 'FILE', $spec, $placement = 'APPEND'). The $mode is either ‘FILE’ or ‘SCRIPT’, depending
on if you’re linking a script or defining one. $spec is either the script file to link or the script source
itself. $placement should be either ‘APPEND’, ‘PREPEND’, or ‘SET’.
HeadScript overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of
the special methods as listed above. Internally, it stores each item as a stdClass token, which it later
serializes using the itemToString() method. This allows you to perform checks on the items in the stack, and
optionally modify these items by simply modifying the object returned.
The HeadScript helper is a concrete implementation of the Placeholder helper.
Note
Use InlineScript for HTML Body Scripts
HeadScript‘s sibling helper, InlineScript, should be used
when you wish to include scripts inline in the HTML body. Placing scripts at the end of your document is a
good practice for speeding up delivery of your page, particularly when using 3rd party analytics scripts.
Note
Arbitrary Attributes are Disabled by Default
By default, HeadScript only will render <script> attributes that are blessed by the W3C. These include
‘type’, ‘charset’, ‘defer’, ‘language’, and ‘src’. However, some javascript frameworks, notably Dojo, utilize
custom attributes in order to modify behavior. To allow such attributes, you can enable them via the
setAllowArbitraryAttributes() method:
| $this->headScript()->setAllowArbitraryAttributes(true);
|
HeadScript Helper Basic Usage
You may specify a new script tag at any time. As noted above, these may be links to outside resource files or
scripts themselves.
| // adding scripts
$this->headScript()->appendFile('/js/prototype.js')
->appendScript($onloadScript);
|
Order is often important with client-side scripting; you may need to ensure that libraries are loaded in a specific
order due to dependencies each have; use the various append, prepend, and offsetSet directives to aid in this task:
| // Putting scripts in order
// place at a particular offset to ensure loaded last
$this->headScript()->offsetSetFile(100, '/js/myfuncs.js');
// use scriptaculous effects (append uses next index, 101)
$this->headScript()->appendFile('/js/scriptaculous.js');
// but always have base prototype script load first:
$this->headScript()->prependFile('/js/prototype.js');
|
When you’re finally ready to output all scripts in your layout script, simply echo the helper:
| <?php echo $this->headScript() ?>
|
Capturing Scripts Using the HeadScript Helper
Sometimes you need to generate client-side scripts programmatically. While you could use string concatenation,
heredocs, and the like, often it’s easier just to do so by creating the script and sprinkling in PHP tags.
HeadScript lets you do just that, capturing it to the stack:
| <?php $this->headScript()->captureStart() ?>
var action = '<?php echo $this->baseUrl ?>';
$('foo_form').action = action;
<?php $this->headScript()->captureEnd() ?>
|
The following assumptions are made:
- The script will be appended to the stack. If you wish for it to replace the stack or be added to the top, you
will need to pass ‘SET’ or ‘PREPEND’, respectively, as the first argument to captureStart().
- The script MIME type is assumed to be ‘text/javascript’; if you wish to specify a different type, you will need
to pass it as the second argument to captureStart().
- If you wish to specify any additional attributes for the <script> tag, pass them in an array as the third
argument to captureStart().
HeadStyle Helper
The HTML <style> element is used to include CSS stylesheets inline in the HTML <head> element.
Note
Use HeadLink to link CSS files
HeadLink should be used to create <link> elements for including
external stylesheets. HeadStyle is used when you wish to define your stylesheets inline.
The HeadStyle helper supports the following methods for setting and adding stylesheet declarations:
- appendStyle($content, $attributes = array())
- offsetSetStyle($index, $content, $attributes = array())
- prependStyle($content, $attributes = array())
- setStyle($content, $attributes = array())
In all cases, $content is the actual CSS declarations. $attributes are any additional attributes you wish
to provide to the style tag: lang, title, media, or dir are all permissible.
Note
Setting Conditional Comments
HeadStyle allows you to wrap the style tag in conditional comments, which allows you to hide it from
specific browsers. To add the conditional tags, pass the conditional value as part of the $attributes
parameter in the method calls.
Headstyle With Conditional Comments
| // adding scripts
$this->headStyle()->appendStyle($styles, array('conditional' => 'lt IE 7'));
|
HeadStyle also allows capturing style declarations; this can be useful if you want to create the declarations
programmatically, and then place them elsewhere. The usage for this will be showed in an example below.
Finally, you can also use the headStyle() method to quickly add declarations elements; the signature for this
is headStyle($content$placement = 'APPEND', $attributes = array()). $placement should be either ‘APPEND’,
‘PREPEND’, or ‘SET’.
HeadStyle overrides each of append(), offsetSet(), prepend(), and set() to enforce usage of the
special methods as listed above. Internally, it stores each item as a stdClass token, which it later serializes
using the itemToString() method. This allows you to perform checks on the items in the stack, and optionally
modify these items by simply modifying the object returned.
The HeadStyle helper is a concrete implementation of the Placeholder helper.
Note
UTF-8 encoding used by default
By default, Zend Framework uses UTF-8 as its default encoding, and, specific to this case, Zend_View does
as well. Character encoding can be set differently on the view object itself using the setEncoding() method
(or the the encoding instantiation parameter). However, since Zend_View_Interface does not define
accessors for encoding, it’s possible that if you are using a custom view implementation with this view helper,
you will not have a getEncoding() method, which is what the view helper uses internally for determining the
character set in which to encode.
If you do not want to utilize UTF-8 in such a situation, you will need to implement a getEncoding() method
in your custom view implementation.
HeadStyle Helper Basic Usage
You may specify a new style tag at any time:
| // adding styles
$this->headStyle()->appendStyle($styles);
|
Order is very important with CSS; you may need to ensure that declarations are loaded in a specific order due to
the order of the cascade; use the various append, prepend, and offsetSet directives to aid in this task:
| // Putting styles in order
// place at a particular offset:
$this->headStyle()->offsetSetStyle(100, $customStyles);
// place at end:
$this->headStyle()->appendStyle($finalStyles);
// place at beginning
$this->headStyle()->prependStyle($firstStyles);
|
When you’re finally ready to output all style declarations in your layout script, simply echo the helper:
| <?php echo $this->headStyle() ?>
|
Capturing Style Declarations Using the HeadStyle Helper
Sometimes you need to generate CSS style declarations programmatically. While you could use string concatenation,
heredocs, and the like, often it’s easier just to do so by creating the styles and sprinkling in PHP tags.
HeadStyle lets you do just that, capturing it to the stack:
| <?php $this->headStyle()->captureStart() ?>
body {
background-color: <?php echo $this->bgColor ?>;
}
<?php $this->headStyle()->captureEnd() ?>
|
The following assumptions are made:
- The style declarations will be appended to the stack. If you wish for them to replace the stack or be added to
the top, you will need to pass ‘SET’ or ‘PREPEND’, respectively, as the first argument to captureStart().
- If you wish to specify any additional attributes for the <style> tag, pass them in an array as the second
argument to captureStart().
HeadTitle Helper
The HTML <title> element is used to provide a title for an HTML document. The HeadTitle helper allows
you to programmatically create and store the title for later retrieval and output.
The HeadTitle helper is a concrete implementation of the Placeholder helper. It overrides the toString() method to enforce generating a
<title> element, and adds a headTitle() method for quick and easy setting and aggregation of title
elements. The signature for that method is headTitle($title, $setType = null); by default, the value is
appended to the stack (aggregating title segments) if left at null, but you may also specify either ‘PREPEND’
(place at top of stack) or ‘SET’ (overwrite stack).
Since setting the aggregating (attach) order on each call to headTitle can be cumbersome, you can set a default
attach order by calling setDefaultAttachOrder() which is applied to all headTitle() calls unless you
explicitly pass a different attach order as the second parameter.
HeadTitle Helper Basic Usage
You may specify a title tag at any time. A typical usage would have you setting title segments for each level of
depth in your application: site, controller, action, and potentially resource.
| // setting the controller and action name as title segments:
$request = Zend_Controller_Front::getInstance()->getRequest();
$this->headTitle($request->getActionName())
->headTitle($request->getControllerName());
// setting the site in the title; possibly in the layout script:
$this->headTitle('Zend Framework');
// setting a separator string for segments:
$this->headTitle()->setSeparator(' / ');
|
When you’re finally ready to render the title in your layout script, simply echo the helper:
| <!-- renders <action> / <controller> / Zend Framework -->
<?php echo $this->headTitle() ?>
|
HTML Object Helpers
The HTML <object> element is used for embedding media like Flash or QuickTime in web pages. The object view
helpers take care of embedding media with minimum effort.
There are four initial Object helpers:
- htmlFlash() Generates markup for embedding Flash files.
- htmlObject() Generates markup for embedding a custom Object.
- htmlPage() Generates markup for embedding other (X)HTML pages.
- htmlQuicktime() Generates markup for embedding QuickTime files.
All of these helpers share a similar interface. For this reason, this documentation will only contain examples of
two of these helpers.
Flash helper
Embedding Flash in your page using the helper is pretty straight-forward. The only required argument is the
resource URI.
| <?php echo $this->htmlFlash('/path/to/flash.swf'); ?>
|
This outputs the following HTML:
| <object data="/path/to/flash.swf"
type="application/x-shockwave-flash"
classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">
</object>
|
Additionally you can specify attributes, parameters and content that can be rendered along with the <object>.
This will be demonstrated using the htmlObject() helper.
Customizing the object by passing additional arguments
The first argument in the object helpers is always required. It is the URI to the resource you want to embed. The
second argument is only required in the htmlObject() helper. The other helpers already contain the correct
value for this argument. The third argument is used for passing along attributes to the object element. It only
accepts an array with key-value pairs. classid and codebase are examples of such attributes. The fourth
argument also only takes a key-value array and uses them to create <param> elements. You will see an example of
this shortly. Lastly, there is the option of providing additional content to the object. Now for an example which
utilizes all arguments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | echo $this->htmlObject(
'/path/to/file.ext',
'mime/type',
array(
'attr1' => 'aval1',
'attr2' => 'aval2'
),
array(
'param1' => 'pval1',
'param2' => 'pval2'
),
'some content'
);
/*
This would output:
<object data="/path/to/file.ext" type="mime/type"
attr1="aval1" attr2="aval2">
<param name="param1" value="pval1" />
<param name="param2" value="pval2" />
some content
</object>
*/
|
InlineScript Helper
The HTML <script> element is used to either provide inline client-side scripting elements or link to a remote
resource containing client-side scripting code. The InlineScript helper allows you to manage both. It is
derived from HeadScript, and any method of that helper is available;
however, use the inlineScript() method in place of headScript().
Note
Use InlineScript for HTML Body Scripts
InlineScript, should be used when you wish to include scripts inline in the HTML body. Placing scripts
at the end of your document is a good practice for speeding up delivery of your page, particularly when using
3rd party analytics scripts.
Some JS libraries need to be included in the HTML head; use HeadScript for those scripts.
JSON Helper
When creating views that return JSON, it’s important to also set the appropriate response header. The JSON view
helper does exactly that. In addition, by default, it disables layouts (if currently enabled), as layouts generally
aren’t used with JSON responses.
The JSON helper sets the following header:
| Content-Type: application/json
|
Most AJAX libraries look for this header when parsing responses to determine how to handle the content.
Usage of the JSON helper is very straightforward:
| <?php echo $this->json($this->data) ?>
|
Note
Keeping layouts and enabling encoding using Zend_Json_Expr
Each method in the JSON helper accepts a second, optional argument. This second argument can be a boolean flag
to enable or disable layouts, or an array of options that will be passed to Zend_Json::encode() and used
internally to encode data.
To keep layouts, the second parameter needs to be boolean TRUE. When the second parameter is an array,
keeping layouts can be achieved by including a keepLayouts key with a value of a boolean TRUE.
| // Boolean true as second argument enables layouts:
echo $this->json($this->data, true);
// Or boolean true as "keepLayouts" key:
echo $this->json($this->data, array('keepLayouts' => true));
|
Zend_Json::encode allows the encoding of native JSON expressions using Zend_Json_Expr objects. This
option is disabled by default. To enable this option, pass a boolean TRUE to the enableJsonExprFinder
key of the options array:
| <?php echo $this->json($this->data, array(
'enableJsonExprFinder' => true,
'keepLayouts' => true,
)) ?>
|
Navigation Helpers
The navigation helpers are used for rendering navigational elements from ZendNavigationContainer instances.
There are 5 built-in helpers:
- Breadcrumbs, used for rendering the path to the
currently active page.
- Links, used for rendering navigational head links (e.g.
<link rel="next" href="..." />)
- Menu, used for rendering menus.
- Sitemap, used for rendering sitemaps conforming to the
Sitemaps XML format.
- Navigation, used for proxying calls to other
navigational helpers.
All built-in helpers extend Zend\View\Helper\Navigation\HelperAbstract, which adds integration with ACL and translation. The abstract class implements the interface
Zend\View\Helper\Navigation\Helper, which defines the following methods:
- getContainer() and setContainer() gets and sets the navigation container the helper should operate on by
default, and hasContainer() checks if the helper has container registered.
- getTranslator() and setTranslator() gets and sets the translator used for translating labels and titles.
getUseTranslator() and setUseTranslator() controls whether the translator should be enabled. The method
hasTranslator() checks if the helper has a translator registered.
- getAcl(), setAcl(), getRole() and setRole(), gets and sets ACL (Zend\Permissions\Acl) instance and role
(String or Zend\Permissions\Acl\Role\RoleInterface) used for filtering out pages when rendering. getUseAcl() and
setUseAcl() controls whether ACL should be enabled. The methods hasAcl() and hasRole() checks if
the helper has an ACL instance or a role registered.
- __toString(), magic method to ensure that helpers can be rendered by echoing the helper instance directly.
- render(), must be implemented by concrete helpers to do the actual rendering.
In addition to the method stubs from the interface, the abstract class also implements the following methods:
- getIndent() and setIndent() gets and sets indentation. The setter accepts a String or an Integer.
In the case of an Integer, the helper will use the given number of spaces for indentation. I.e.,
setIndent(4) means 4 initial spaces of indentation. Indentation can be specified for all helpers except the
Sitemap helper.
- getMinDepth() and setMinDepth() gets and sets the minimum depth a page must have to be included by the
helper. Setting NULL means no minimum depth.
- getMaxDepth() and setMaxDepth() gets and sets the maximum depth a page can have to be included by the
helper. Setting NULL means no maximum depth.
- getRenderInvisible() and setRenderInvisible() gets and sets whether to render items that have been marked
as invisible or not.
- __call() is used for proxying calls to the container registered in the helper, which means you can call
methods on a helper as if it was a container. See example below.
- findActive($container, $minDepth, $maxDepth) is used for finding the deepest active page in the given
container. If depths are not given, the method will use the values retrieved from getMinDepth() and
getMaxDepth(). The deepest active page must be between $minDepth and $maxDepth inclusively. Returns
an array containing a reference to the found page instance and the depth at which the page was found.
- htmlify() renders an ‘a’ HTML element from a Zend\Navigation\Page instance.
- accept() is used for determining if a page should be accepted when iterating containers. This method checks
for page visibility and verifies that the helper’s role is allowed access to the page’s resource and privilege.
- The static method setDefaultAcl() is used for setting a default ACL object that will be used by helpers.
- The static method setDefaultRole() is used for setting a default ACL that will be used by helpers
If a container is not explicitly set, the helper will create an empty Zend\Navigation
container when calling $helper->getContainer().
Proxying calls to the navigation container
Navigation view helpers use the magic method __call() to proxy method calls to the navigation container that is
registered in the view helper.
| $this->navigation()->addPage(array(
'type' => 'uri',
'label' => 'New page'));
|
The call above will add a page to the container in the Navigation helper.
Translation of labels and titles
The navigation helpers support translation of page labels and titles. You can set a translator of type
Zend\I18n\Translator in the helper using $helper->setTranslator($translator).
If you want to disable translation, use $helper->setUseTranslator(false).
The proxy helper will inject its own translator to the
helper it proxies to if the proxied helper doesn’t already have a translator.
Note
There is no translation in the sitemap helper, since there are no page labels or titles involved in an XML
sitemap.
Integration with ACL
All navigational view helpers support ACL inherently from the class
Zend\View\Helper\Navigation\HelperAbstract. A Zend\Permissions\Acl object can be assigned to a helper instance with
$helper->setAcl($acl), and role with $helper->setRole(‘member’) or $helper->setRole(new
ZendPermissionsAclRoleGenericRole(‘member’)). If ACL is used in the helper, the role in the helper must be allowed by the ACL to
access a page’s resource and/or have the page’s privilege for the page to be included when rendering.
If a page is not accepted by ACL, any descendant page will also be excluded from rendering.
The proxy helper will inject its own ACL and role to the
helper it proxies to if the proxied helper doesn’t already have any.
The examples below all show how ACL affects rendering.
Navigation setup used in examples
This example shows the setup of a navigation container for a fictional software company.
Notes on the setup:
- The domain for the site is www.example.com.
- Interesting page properties are marked with a comment.
- Unless otherwise is stated in other examples, the user is requesting the URL
http://www.example.com/products/server/faq/, which translates to the page labeled FAQ under Foo Server.
- The assumed ACL and router setup is shown below the container setup.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168 | /*
* Navigation container (config/array)
* Each element in the array will be passed to
* Zend\Navigation\Page::factory() when constructing
* the navigation container below.
*/
$pages = array(
array(
'label' => 'Home',
'title' => 'Go Home',
'module' => 'default',
'controller' => 'index',
'action' => 'index',
'order' => -100 // make sure home is the first page
),
array(
'label' => 'Special offer this week only!',
'module' => 'store',
'controller' => 'offer',
'action' => 'amazing',
'visible' => false // not visible
),
array(
'label' => 'Products',
'module' => 'products',
'controller' => 'index',
'action' => 'index',
'pages' => array(
array(
'label' => 'Foo Server',
'module' => 'products',
'controller' => 'server',
'action' => 'index',
'pages' => array(
array(
'label' => 'FAQ',
'module' => 'products',
'controller' => 'server',
'action' => 'faq',
'rel' => array(
'canonical' => 'http://www.example.com/?page=faq',
'alternate' => array(
'module' => 'products',
'controller' => 'server',
'action' => 'faq',
'params' => array('format' => 'xml')
)
)
),
array(
'label' => 'Editions',
'module' => 'products',
'controller' => 'server',
'action' => 'editions'
),
array(
'label' => 'System Requirements',
'module' => 'products',
'controller' => 'server',
'action' => 'requirements'
)
)
),
array(
'label' => 'Foo Studio',
'module' => 'products',
'controller' => 'studio',
'action' => 'index',
'pages' => array(
array(
'label' => 'Customer Stories',
'module' => 'products',
'controller' => 'studio',
'action' => 'customers'
),
array(
'label' => 'Support',
'module' => 'prodcts',
'controller' => 'studio',
'action' => 'support'
)
)
)
)
),
array(
'label' => 'Company',
'title' => 'About us',
'module' => 'company',
'controller' => 'about',
'action' => 'index',
'pages' => array(
array(
'label' => 'Investor Relations',
'module' => 'company',
'controller' => 'about',
'action' => 'investors'
),
array(
'label' => 'News',
'class' => 'rss', // class
'module' => 'company',
'controller' => 'news',
'action' => 'index',
'pages' => array(
array(
'label' => 'Press Releases',
'module' => 'company',
'controller' => 'news',
'action' => 'press'
),
array(
'label' => 'Archive',
'route' => 'archive', // route
'module' => 'company',
'controller' => 'news',
'action' => 'archive'
)
)
)
)
),
array(
'label' => 'Community',
'module' => 'community',
'controller' => 'index',
'action' => 'index',
'pages' => array(
array(
'label' => 'My Account',
'module' => 'community',
'controller' => 'account',
'action' => 'index',
'resource' => 'mvc:community.account' // resource
),
array(
'label' => 'Forums',
'uri' => 'http://forums.example.com/',
'class' => 'external' // class
)
)
),
array(
'label' => 'Administration',
'module' => 'admin',
'controller' => 'index',
'action' => 'index',
'resource' => 'mvc:admin', // resource
'pages' => array(
array(
'label' => 'Write new article',
'module' => 'admin',
'controller' => 'post',
'aciton' => 'write'
)
)
)
);
// Create container from array
$container = new Zend\Navigation($pages);
// Store the container in the proxy helper:
$view->getHelper('navigation')->setContainer($container);
// ...or simply:
$view->navigation($container);
|
In addition to the container above, the following setup is assumed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | // Setup router (default routes and 'archive' route):
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$router->addDefaultRoutes();
$router->addRoute(
'archive',
new Zend_Controller_Router_Route(
'/archive/:year',
array(
'module' => 'company',
'controller' => 'news',
'action' => 'archive',
'year' => (int) date('Y') - 1
),
array('year' => '\d+')
)
);
// Setup ACL:
$acl = new Zend\Permissions\Acl\Acl();
$acl->addRole(new Zend\Permissions\Acl\Role\GenericRole('member'));
$acl->addRole(new Zend\Permissions\Acl\Role\GenericRole('admin'));
$acl->add(new Zend\Permissions\Acl\Resource\GenericResource('mvc:admin'));
$acl->add(new Zend\Permissions\Acl\Resource\GenericResource('mvc:community.account'));
$acl->allow('member', 'mvc:community.account');
$acl->allow('admin', null);
// Store ACL and role in the proxy helper:
$view->navigation()->setAcl($acl)->setRole('member');
// ...or set default ACL and role statically:
Zend\View\Helper\Navigation\HelperAbstract::setDefaultAcl($acl);
Zend\View\Helper\Navigation\HelperAbstract::setDefaultRole('member');
|
Breadcrumbs Helper
Breadcrumbs are used for indicating where in a sitemap a user is currently browsing, and are typically rendered
like this: “You are here: Home > Products > FantasticProduct 1.0”. The breadcrumbs helper follows the guidelines
from Breadcrumbs Pattern - Yahoo! Design Pattern Library, and allows simple customization (minimum/maximum
depth, indentation, separator, and whether the last element should be linked), or rendering using a partial view
script.
The Breadcrumbs helper works like this; it finds the deepest active page in a navigation container, and renders an
upwards path to the root. For MVC pages, the “activeness” of a page is determined by inspecting the request
object, as stated in the section on ZendNavigationPageMvc.
The helper sets the minDepth property to 1 by default, meaning breadcrumbs will not be rendered if the deepest
active page is a root page. If maxDepth is specified, the helper will stop rendering when at the specified depth
(e.g. stop at level 2 even if the deepest active page is on level 3).
Methods in the breadcrumbs helper:
- {get|set}Separator() gets/sets separator string that is used between breadcrumbs. Defualt is ‘ > ‘.
- {get|set}LinkLast() gets/sets whether the last breadcrumb should be rendered as an anchor or not. Default is
FALSE.
- {get|set}Partial() gets/sets a partial view script that should be used for rendering breadcrumbs. If a partial
view script is set, the helper’s render() method will use the renderPartial() method. If no partial is
set, the renderStraight() method is used. The helper expects the partial to be a String or an Array
with two elements. If the partial is a String, it denotes the name of the partial script to use. If it is an
Array, the first element will be used as the name of the partial view script, and the second element is the
module where the script is found.
- renderStraight() is the default render method.
- renderPartial() is used for rendering using a partial view script.
Rendering breadcrumbs
This example shows how to render breadcrumbs with default settings.
| In a view script or layout:
<?php echo $this->navigation()->breadcrumbs(); ?>
The two calls above take advantage of the magic __toString() method,
and are equivalent to:
<?php echo $this->navigation()->breadcrumbs()->render(); ?>
Output:
<a href="/products">Products</a> > <a href="/products/server">Foo Server</a> > FAQ
|
Specifying indentation
This example shows how to render breadcrumbs with initial indentation.
| Rendering with 8 spaces indentation:
<?php echo $this->navigation()->breadcrumbs()->setIndent(8);?>
Output:
<a href="/products">Products</a> > <a href="/products/server">Foo Server</a> > FAQ
|
Customize breadcrumbs output
This example shows how to customze breadcrumbs output by specifying various options.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | In a view script or layout:
<?php
echo $this->navigation()
->breadcrumbs()
->setLinkLast(true) // link last page
->setMaxDepth(1) // stop at level 1
->setSeparator(' ▶' . PHP_EOL); // cool separator with newline
?>
Output:
<a href="/products">Products</a> ▶
<a href="/products/server">Foo Server</a>
/////////////////////////////////////////////////////
Setting minimum depth required to render breadcrumbs:
<?php
$this->navigation()->breadcrumbs()->setMinDepth(10);
echo $this->navigation()->breadcrumbs();
?>
Output:
Nothing, because the deepest active page is not at level 10 or deeper.
|
Rendering breadcrumbs using a partial view script
This example shows how to render customized breadcrumbs using a partial vew script. By calling setPartial(),
you can specify a partial view script that will be used when calling render(). When a partial is specified, the
renderPartial() method will be called. This method will find the deepest active page and pass an array of pages
that leads to the active page to the partial view script.
In a layout:
| $partial = ;
echo $this->navigation()->breadcrumbs()
->setPartial(array('breadcrumbs.phtml', 'default'));
|
Contents of application/modules/default/views/breadcrumbs.phtml:
| echo implode(', ', array_map(
create_function('$a', 'return $a->getLabel();'),
$this->pages));
|
Output:
| Products, Foo Server, FAQ
|
Links Helper
The links helper is used for rendering HTML LINK elements. Links are used for describing document
relationships of the currently active page. Read more about links and link types at Document relationships: the
LINK element (HTML4 W3C Rec.) and Link types (HTML4 W3C Rec.) in the HTML4 W3C Recommendation.
There are two types of relations; forward and reverse, indicated by the keyords ‘rel’ and ‘rev’. Most methods
in the helper will take a $rel param, which must be either ‘rel’ or ‘rev’. Most methods also take a
$type param, which is used for specifying the link type (e.g. alternate, start, next, prev, chapter, etc).
Relationships can be added to page objects manually, or found by traversing the container registered in the helper.
The method findRelation($page, $rel, $type) will first try to find the given $rel of $type from the
$page by calling $page->findRel($type) or $page->findRel($type). If the $page has a relation that can
be converted to a page instance, that relation will be used. If the $page instance doesn’t have the specified
$type, the helper will look for a method in the helper named search$rel$type (e.g. searchRelNext() or
searchRevAlternate()). If such a method exists, it will be used for determining the $page‘s relation by
traversing the container.
Not all relations can be determined by traversing the container. These are the relations that will be found by
searching:
- searchRelStart(), forward ‘start’ relation: the first page in the container.
- searchRelNext(), forward ‘next’ relation; finds the next page in the container, i.e. the page after the
active page.
- searchRelPrev(), forward ‘prev’ relation; finds the previous page, i.e. the page before the active page.
- searchRelChapter(), forward ‘chapter’ relations; finds all pages on level 0 except the ‘start’ relation or
the active page if it’s on level 0.
- searchRelSection(), forward ‘section’ relations; finds all child pages of the active page if the active page
is on level 0 (a ‘chapter’).
- searchRelSubsection(), forward ‘subsection’ relations; finds all child pages of the active page if the active
pages is on level 1 (a ‘section’).
- searchRevSection(), reverse ‘section’ relation; finds the parent of the active page if the active page is on
level 1 (a ‘section’).
- searchRevSubsection(), reverse ‘subsection’ relation; finds the parent of the active page if the active page
is on level 2 (a ‘subsection’).
Note
When looking for relations in the page instance ($page->getRel($type) or $page->getRev($type)), the helper
accepts the values of type String, Array, Zend\Config, or Zend\Navigation\Page. If a string is
found, it will be converted to a Zend\Navigation\Page\Uri. If an array or a config is found, it will be
converted to one or several page instances. If the first key of the array/config is numeric, it will be
considered to contain several pages, and each element will be passed to the page factory. If the first key is not numeric, the array/config will be passed to the page
factory directly, and a single page will be returned.
The helper also supports magic methods for finding relations. E.g. to find forward alternate relations, call
$helper->findRelAlternate($page), and to find reverse section relations, call $helper->findRevSection($page).
Those calls correspond to $helper->findRelation($page, ‘rel’, ‘alternate’); and $helper->findRelation($page,
‘rev’, ‘section’); respectively.
To customize which relations should be rendered, the helper uses a render flag. The render flag is an integer
value, and will be used in a bitwse and (&) operation against the helper’s render constants to determine if the
relation that belongs to the render constant should be rendered.
See the example below for more information.
- Zend\View\Helper\Navigation\Links::RENDER_ALTERNATE
- Zend\View\Helper\Navigation\Links::RENDER_STYLESHEET
- Zend\View\Helper\Navigation\Links::RENDER_START
- Zend\View\Helper\Navigation\Links::RENDER_NEXT
- Zend\View\Helper\Navigation\Links:::RENDER_PREV
- Zend\View\Helper\Navigation\Links::RENDER_CONTENTS
- Zend\View\Helper\Navigation\Links::RENDER_INDEX
- Zend\View\Helper\Navigation\Links::RENDER_GLOSSARY
- Zend\View\Helper\Navigation\Links:::RENDER_COPYRIGHT
- Zend\View\Helper\Navigation\Links::RENDER_CHAPTER
- Zend\View\Helper\Navigation\Links::RENDER_SECTION
- Zend\View\Helper\Navigation\Links::RENDER_SUBSECTION
- Zend\View\Helper\Navigation\Links::RENDER_APPENDIX
- Zend\View\Helper\Navigation\Links::RENDER_HELP
- Zend\View\Helper\Navigation\Links::RENDER_BOOKMARK
- Zend\View\Helper\Navigation\Links::RENDER_CUSTOM
- Zend\View\Helper\Navigation\Links::RENDER_ALL
The constants from RENDER_ALTERNATE to RENDER_BOOKMARK denote standard HTML link types. RENDER_CUSTOM
denotes non-standard relations that specified in pages. RENDER_ALL denotes standard and non-standard relations.
Methods in the links helper:
- {get|set}RenderFlag() gets/sets the render flag. Default is RENDER_ALL. See examples below on how to set
the render flag.
- findAllRelations() finds all relations of all types for a given page.
- findRelation() finds all relations of a given type from a given page.
- searchRel{Start|Next|Prev|Chapter|Section|Subsection}() traverses a container to find forward relations to the
start page, the next page, the previous page, chapters, sections, and subsections.
- searchRev{Section|Subsection}() traverses a container to find reverse relations to sections or subsections.
- renderLink() renders a single link element.
Specify relations in pages
This example shows how to specify relations in pages.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | $container = new Zend\Navigation(array(
array(
'label' => 'Relations using strings',
'rel' => array(
'alternate' => 'http://www.example.org/'
),
'rev' => array(
'alternate' => 'http://www.example.net/'
)
),
array(
'label' => 'Relations using arrays',
'rel' => array(
'alternate' => array(
'label' => 'Example.org',
'uri' => 'http://www.example.org/'
)
)
),
array(
'label' => 'Relations using configs',
'rel' => array(
'alternate' => new Zend\Config(array(
'label' => 'Example.org',
'uri' => 'http://www.example.org/'
))
)
),
array(
'label' => 'Relations using pages instance',
'rel' => array(
'alternate' => Zend\Navigation\Page::factory(array(
'label' => 'Example.org',
'uri' => 'http://www.example.org/'
))
)
)
));
|
Default rendering of links
This example shows how to render a menu from a container registered/found in the view helper.
1
2
3
4
5
6
7
8
9
10
11
12
13 | In a view script or layout:
<?php echo $this->view->navigation()->links(); ?>
Output:
<link rel="alternate" href="/products/server/faq/format/xml">
<link rel="start" href="/" title="Home">
<link rel="next" href="/products/server/editions" title="Editions">
<link rel="prev" href="/products/server" title="Foo Server">
<link rel="chapter" href="/products" title="Products">
<link rel="chapter" href="/company/about" title="Company">
<link rel="chapter" href="/community" title="Community">
<link rel="canonical" href="http://www.example.com/?page=server-faq">
<link rev="subsection" href="/products/server" title="Foo Server">
|
Specify which relations to render
This example shows how to specify which relations to find and render.
| Render only start, next, and prev:
$helper->setRenderFlag(Zend\View\Helper\Navigation\Links::RENDER_START |
Zend\View\Helper\Navigation\Links::RENDER_NEXT |
Zend\View\Helper\Navigation\Links::RENDER_PREV);
Output:
<link rel="start" href="/" title="Home">
<link rel="next" href="/products/server/editions" title="Editions">
<link rel="prev" href="/products/server" title="Foo Server">
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | Render only native link types:
$helper->setRenderFlag(Zend\View\Helper\Navigation\Links::RENDER_ALL ^
Zend\View\Helper\Navigation\Links::RENDER_CUSTOM);
Output:
<link rel="alternate" href="/products/server/faq/format/xml">
<link rel="start" href="/" title="Home">
<link rel="next" href="/products/server/editions" title="Editions">
<link rel="prev" href="/products/server" title="Foo Server">
<link rel="chapter" href="/products" title="Products">
<link rel="chapter" href="/company/about" title="Company">
<link rel="chapter" href="/community" title="Community">
<link rev="subsection" href="/products/server" title="Foo Server">
|
| Render all but chapter:
$helper->setRenderFlag(Zend\View\Helper\Navigation\Links::RENDER_ALL ^
Zend\View\Helper\Navigation\Links::RENDER_CHAPTER);
Output:
<link rel="alternate" href="/products/server/faq/format/xml">
<link rel="start" href="/" title="Home">
<link rel="next" href="/products/server/editions" title="Editions">
<link rel="prev" href="/products/server" title="Foo Server">
<link rel="canonical" href="http://www.example.com/?page=server-faq">
<link rev="subsection" href="/products/server" title="Foo Server">
|
Sitemap Helper
The Sitemap helper is used for generating XML sitemaps, as defined by the Sitemaps XML format. Read more about
Sitemaps on Wikpedia.
By default, the sitemap helper uses sitemap validators to validate each element
that is rendered. This can be disabled by calling $helper->setUseSitemapValidators(false).
Note
If you disable sitemap validators, the custom properties (see table) are not validated at all.
The sitemap helper also supports Sitemap XSD Schema validation of the generated sitemap. This is disabled by
default, since it will require a request to the Schema file. It can be enabled with
$helper->setUseSchemaValidation(true).
Sitemap XML elements
Element |
Description |
loc |
Absolute URL to page. An absolute URL will be generated by the helper. |
lastmod |
The date of last modification of the file, in W3C Datetime format. This time portion can be omitted if desired, and only use YYYY-MM-DD. The helper will try to retrieve the lastmod value from the page’s custom property lastmod if it is set in the page. If the value is not a valid date, it is ignored. |
changefreq |
How frequently the page is likely to change. This value provides general information to search engines and may not correlate exactly to how often they crawl the page. Valid values are: alwayshourlydailyweeklymonthlyyearlynever The helper will try to retrieve the changefreq value from the page’s custom property changefreq if it is set in the page. If the value is not valid, it is ignored. |
priority |
The priority of this URL relative to other URLs on your site. Valid values range from 0.0 to 1.0. The helper will try to retrieve the priority value from the page’s custom property priority if it is set in the page. If the value is not valid, it is ignored. |
Methods in the sitemap helper:
- {get|set}FormatOutput() gets/sets a flag indicating whether XML output should be formatted. This corresponds
to the formatOutput property of the native DOMDocument class. Read more at PHP: DOMDocument - Manual.
Default is FALSE.
- {get|set}UseXmlDeclaration() gets/sets a flag indicating whether the XML declaration should be included when
rendering. Default is TRUE.
- {get|set}UseSitemapValidators() gets/sets a flag indicating whether sitemap validators should be used when
generating the DOM sitemap. Default is TRUE.
- {get|set}UseSchemaValidation() gets/sets a flag indicating whether the helper should use XML Schema
validation when generating the DOM sitemap. Default is FALSE. If TRUE.
- {get|set}ServerUrl() gets/sets server URL that will be prepended to non-absolute URLs in the url()
method. If no server URL is specified, it will be determined by the helper.
- url() is used to generate absolute URLs to pages.
- getDomSitemap() generates a DOMDocument from a given container.
Rendering an XML sitemap
This example shows how to render an XML sitemap based on the setup we did further up.
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | // In a view script or layout:
// format output
$this->navigation()
->sitemap()
->setFormatOutput(true); // default is false
// other possible methods:
// ->setUseXmlDeclaration(false); // default is true
// ->setServerUrl('http://my.otherhost.com');
// default is to detect automatically
// print sitemap
echo $this->navigation()->sitemap();
|
Notice how pages that are invisible or pages with ACL roles incompatible with the view helper are filtered out:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 | <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.com/</loc>
</url>
<url>
<loc>http://www.example.com/products</loc>
</url>
<url>
<loc>http://www.example.com/products/server</loc>
</url>
<url>
<loc>http://www.example.com/products/server/faq</loc>
</url>
<url>
<loc>http://www.example.com/products/server/editions</loc>
</url>
<url>
<loc>http://www.example.com/products/server/requirements</loc>
</url>
<url>
<loc>http://www.example.com/products/studio</loc>
</url>
<url>
<loc>http://www.example.com/products/studio/customers</loc>
</url>
<url>
<loc>http://www.example.com/prodcts/studio/support</loc>
</url>
<url>
<loc>http://www.example.com/company/about</loc>
</url>
<url>
<loc>http://www.example.com/company/about/investors</loc>
</url>
<url>
<loc>http://www.example.com/company/news</loc>
</url>
<url>
<loc>http://www.example.com/company/news/press</loc>
</url>
<url>
<loc>http://www.example.com/archive</loc>
</url>
<url>
<loc>http://www.example.com/community</loc>
</url>
<url>
<loc>http://www.example.com/community/account</loc>
</url>
<url>
<loc>http://forums.example.com/</loc>
</url>
</urlset>
|
Render the sitemap using no ACL role (should filter out /community/account):
| echo $this->navigation()
->sitemap()
->setFormatOutput(true)
->setRole();
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 | <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.com/</loc>
</url>
<url>
<loc>http://www.example.com/products</loc>
</url>
<url>
<loc>http://www.example.com/products/server</loc>
</url>
<url>
<loc>http://www.example.com/products/server/faq</loc>
</url>
<url>
<loc>http://www.example.com/products/server/editions</loc>
</url>
<url>
<loc>http://www.example.com/products/server/requirements</loc>
</url>
<url>
<loc>http://www.example.com/products/studio</loc>
</url>
<url>
<loc>http://www.example.com/products/studio/customers</loc>
</url>
<url>
<loc>http://www.example.com/prodcts/studio/support</loc>
</url>
<url>
<loc>http://www.example.com/company/about</loc>
</url>
<url>
<loc>http://www.example.com/company/about/investors</loc>
</url>
<url>
<loc>http://www.example.com/company/news</loc>
</url>
<url>
<loc>http://www.example.com/company/news/press</loc>
</url>
<url>
<loc>http://www.example.com/archive</loc>
</url>
<url>
<loc>http://www.example.com/community</loc>
</url>
<url>
<loc>http://forums.example.com/</loc>
</url>
</urlset>
|
Render the sitemap using a maximum depth of 1.
| echo $this->navigation()
->sitemap()
->setFormatOutput(true)
->setMaxDepth(1);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 | <?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://www.example.com/</loc>
</url>
<url>
<loc>http://www.example.com/products</loc>
</url>
<url>
<loc>http://www.example.com/products/server</loc>
</url>
<url>
<loc>http://www.example.com/products/studio</loc>
</url>
<url>
<loc>http://www.example.com/company/about</loc>
</url>
<url>
<loc>http://www.example.com/company/about/investors</loc>
</url>
<url>
<loc>http://www.example.com/company/news</loc>
</url>
<url>
<loc>http://www.example.com/community</loc>
</url>
<url>
<loc>http://www.example.com/community/account</loc>
</url>
<url>
<loc>http://forums.example.com/</loc>
</url>
</urlset>
|
Note
UTF-8 encoding used by default
By default, Zend Framework uses UTF-8 as its default encoding, and, specific to this case, Zend\View does
as well. Character encoding can be set differently on the view object itself using the setEncoding() method
(or the the encoding instantiation parameter). However, since Zend\View\Interface does not define
accessors for encoding, it’s possible that if you are using a custom view implementation with the Dojo view
helper, you will not have a getEncoding() method, which is what the view helper uses internally for
determining the character set in which to encode.
If you do not want to utilize UTF-8 in such a situation, you will need to implement a getEncoding() method
in your custom view implementation.
Navigation Helper
The Navigation helper is a proxy helper that relays calls to other navigational helpers. It can be considered an
entry point to all navigation-related view tasks. The aforementioned navigational helpers are in the namespace
Zend\View\Helper\Navigation, and would thus require the path Zend/View/Helper/Navigation to be added as a
helper path to the view. With the proxy helper residing in the Zend\View\Helper namespace, it will always be
available, without the need to add any helper paths to the view.
The Navigation helper finds other helpers that implement the Zend\View\Helper\Navigation\Helper interface,
which means custom view helpers can also be proxied. This would, however, require that the custom helper path is
added to the view.
When proxying to other helpers, the Navigation helper can inject its container, ACL/role, and translator. This
means that you won’t have to explicitly set all three in all navigational helpers, nor resort to injecting by means
of static methods.
- findHelper() finds the given helper, verifies that it is a navigational helper, and injects container,
ACL/role and translator.
- {get|set}InjectContainer() gets/sets a flag indicating whether the container should be injected to proxied
helpers. Default is TRUE.
- {get|set}InjectAcl() gets/sets a flag indicating whether the ACL/role should be injected to proxied helpers.
Default is TRUE.
- {get|set}InjectTranslator() gets/sets a flag indicating whether the translator should be injected to proxied
helpers. Default is TRUE.
- {get|set}DefaultProxy() gets/sets the default proxy. Default is ‘menu’.
- render() proxies to the render method of the default proxy.
Registering Helpers
Zend\View\Renderer\PhpRenderer composes a plugin broker for managing
helpers, specifically an instance of Zend\View\HelperBroker, which extends the base plugin broker in order to
ensure we have valid helpers available. The HelperBroker by default uses Zend\View\HelperLoader as its
helper locator. The HelperLoader is a map-based loader, which means that you will simply map the helper/plugin
name by which you wish to refer to it to the actual class name of the helper/plugin.
Programmatically, this is done as follows:
1
2
3
4
5
6
7
8
9
10
11
12 | // $view is an instance of PhpRenderer
$broker = $view->getBroker();
$loader = $broker->getClassLoader();
// Register singly:
$loader->registerPlugin('lowercase', 'My\Helper\LowerCase');
// Register several:
$loader->registerPlugins(array(
'lowercase' => 'My\Helper\LowerCase',
'uppercase' => 'My\Helper\UpperCase',
));
|
Within an MVC application, you will typically simply pass a map of plugins to the class via your configuration.
| // From within a configuration file
return array(
'di' => array('instance' => array(
'Zend\View\HelperLoader' => array('parameters' => array(
'map' => array(
'lowercase' => 'My\Helper\LowerCase',
'uppercase' => 'My\Helper\UpperCase',
),
)),
)),
);
|
The above can be done in each module that needs to register helpers with the PhpRenderer; however, be aware
that another module can register helpers with the same name, so order of modules can impact which helper class will
actually be registered!
Writing Custom Helpers
Writing custom helpers is easy. We recommend extending Zend\View\Helper\AbstractHelper, but at the minimum, you
need only implement the Zend\View\Helper interface:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 | namespace Zend\View;
interface Helper
{
/**
* Set the View object
*
* @param Renderer $view
* @return Helper
*/
public function setView(Renderer $view);
/**
* Get the View object
*
* @return Renderer
*/
public function getView();
}
|
If you want your helper to be capable of being invoked as if it were a method call of the PhpRenderer, you
should also implement an __invoke() method within your helper.
As previously noted, we recommend extending Zend\View\Helper\AbstractHelper, as it implements the methods
defined in Helper, giving you a headstart in your development.
Once you have defined your helper class, make sure you can autoload it, and then register it with the plugin
broker.
Here is an example helper, which we’re titling “SpecialPurpose”
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | namespace My\View\Helper;
use Zend\View\Helper\AbstractHelper;
class SpecialPurpose extends AbstractHelper
{
protected $count = 0;
public function __invoke()
{
$this->count++;
$output = sprintf("I have seen 'The Jerk' %d time(s).", $this->count);
return htmlspecialchars($output, ENT_QUOTES, 'UTF-8');
}
}
|
Then assume that when we register it with the plugin broker, we map it to the
string “specialpurpose”.
Within a view script, you can call the SpecialPurpose helper as many times as you like; it will be instantiated
once, and then it persists for the life of that PhpRenderer instance.
| // remember, in a view script, $this refers to the Zend_View instance.
echo $this->specialPurpose();
echo $this->specialPurpose();
echo $this->specialPurpose();
|
The output would look something like this:
| I have seen 'The Jerk' 1 time(s).
I have seen 'The Jerk' 2 time(s).
I have seen 'The Jerk' 3 time(s).
|
Sometimes you will need access to the calling PhpRenderer object – for instance, if you need to use the
registered encoding, or want to render another view script as part of your helper. This is why we define the
setView() and getView() methods. As an example, we could rewrite the SpecialPurpose helper as follows
to take advantage of the EscapeHtml helper:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 | namespace My\View\Helper;
use Zend\View\Helper\AbstractHelper;
class SpecialPurpose extends AbstractHelper
{
protected $count = 0;
public function __invoke()
{
$this->count++;
$output = sprintf("I have seen 'The Jerk' %d time(s).", $this->count);
$escaper = $this->getView()->plugin('escapehtml');
return $escaper($output);
}
}
|
Registering Concrete Helpers
Sometimes it is convenient to instantiate a view helper, and then register it with the renderer. This can be done
by injecting it directly into the plugin broker.
| // $view is a PhpRenderer instance
$helper = new My_Helper_Foo();
// ...do some configuration or dependency injection...
$view->getBroker()->register('foo', $helper);
|
When registered, the plugin broker will inject the PhpRenderer instance into the helper.