PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Decorators

Creating the markup for a form is often a time-consuming task, particularly if you plan on re-using the same markup to show things such as validation errors, submitted values, etc. Zend_Form's answer to this issue is decorators.

Decorators for Zend_Form objects can be used to render a form. The FormElements decorator will iterate through all items in a form -- elements, display groups, and sub forms -- and render them, returning the result. Additional decorators may then be used to wrap this content, or append or prepend it.

The default decorators for Zend_Form are FormElements, HtmlTag (wraps in a definition list), and Form; the equivalent code for creating them is as follows:

<?php
$form
->setDecorators(array(
    
'FormElements',
    array(
'HtmlTag', array('tag' => 'dl')),
    
'Form'
));

This creates output like the following:

<form action="/form/action" method="post">
<dl>
...
</dl>
</form>

Any attributes set on the form object will be used as HTML attributes of the <form> tag.

Default Decorators Do Not Need to Be Loaded

By default, the default decorators are loaded during object initialization. You can disable this by passing the 'disableLoadDefaultDecorators' option to the constructor:

<?php
$form 
= new Zend_Form(array('disableLoadDefaultDecorators' => true));

This option may be mixed with any other options you pass, both as array options or in a Zend_Config object.

Using Multiple Decorators of the Same Type

Internally, Zend_Form uses a decorator's class as the lookup mechanism when retrieving decorators. As a result, you cannot register multiple decorators of the same type; subsequent decorators will simply overwrite those that existed before.

To get around this, you can use aliases. Instead of passing a decorator or decorator name as the first argument to addDecorator(), pass an array with a single element, with the alias pointing to the decorator object or name:

<?php
// Alias to 'FooBar':
$form->addDecorator(array('FooBar' => 'HtmlTag'), array('tag' => 'div'));

// And retrieve later:
$form $element->getDecorator('FooBar');

In the addDecorators() and setDecorators() methods, you will need to pass the 'decorator' option in the array representing the decorator:

<?php
// Add two 'HtmlTag' decorators, aliasing one to 'FooBar':
$form->addDecorators(
    array(
'HtmlTag', array('tag' => 'div')),
    array(
        
'decorator' => array('FooBar' => 'HtmlTag'),
        
'options' => array('tag' => 'dd')
    ),
);

// And retrieve later:
$htmlTag $form->getDecorator('HtmlTag');
$fooBar  $form->getDecorator('FooBar');

You may create your own decorators for generating the form. One common use case is if you know the exact HTML you wish to use; your decorator could create the exact HTML and simply return it, potentially using the decorators from individual elements or display groups.

The following methods may be used to interact with decorators:

  • addDecorator($decorator, $options = null)

  • addDecorators(array $decorators)

  • setDecorators(array $decorators)

  • getDecorator($name)

  • getDecorators()

  • removeDecorator($name)

  • clearDecorators()

Zend_Form also uses overloading to allow rendering specific decorators. __call() will intercept methods that lead with the text 'render' and use the remainder of the method name to lookup a decorator; if found, it will then render that single decorator. Any arguments passed to the method call will be used as content to pass to the decorator's render() method. As an example:

<?php
// Render only the FormElements decorator:
echo $form->renderFormElements();

// Render only the fieldset decorator, passing in content:
echo $form->renderFieldset("<p>This is fieldset content</p>");

If the decorator does not exist, an exception is raised.

Zend Framework