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.




