Related download: Configure standard Zend Form Decorators
After having ‘attended’ the Zend webinar about Zend Form Decorators I wasn’t quite sure about what I had just learned. I was just looking for an easy way to setup up my decorators for the forms I use, site-wide or on a per-module basis. As I am happy with the existing decorators and the need to write my own hasn’t presented itself yet.
In this post I write about using the standard decorators and how to configure them in an easy way without having to add them in your element definitions but with keeping the possibility to do so. As there are enough post about Zend Form and its decorators I will not go into how to write your own decorators and how to use then in your forms. I have made the assumption that the reader understands how decorators work and how their output creates what we know as the Zend_Form output.
What am I thinking:
Just to get our heads around what all is involved to get those standard decorators under control we have to know how the Zend Form works and where and how decorators are used. The default form decorators are loaded after instantiation through the usage of loadDefaultDecorators() in the following classes:
For me this was the hard part, to find a uniform way to change the loaded defaults and keep existing functionality. I decided to approach it in two ways. One is to set these defaults through the use of Zend_Config_Ini, and another way through the usage of class properties. The latter is my least favorite because you would have to get into the code to change the settings but It could be favored by others since no separate ini file parsing is needed. I will explain the first below, both are available through the related dowload.
Sub classing Zend Form was inevitable as I wanted to override the default decorators loaded. As you see for certain form element classes; they override the loadDefaultDecorators method to set their own defaults. Have a look at for example the Zend_Form_Element_Submit, here you can see that not all elements load the same decorators. My goal though was to keep existing behavior, I don’t want to subclass all the Zend_Form_Element classes and change their defaults by overriding the loadDefaultDecorators() method (Which is actually yet another option to work part of this problem).
What I ended up doing is overriding the Zend Form constructor and the addElement method. In the constructor I parse the ini file which contains my default -per element- setting such as the one below.
Example config element
[button]
tooltip.decorator = "ToolTip"
viewhelper.decorator = "ViewHelper"
htmltag.decorator = "HtmlTag"
htmltag.options.tag = "div"
In the constructor I also set the form’s decorators, then in the overridden addElement I have added the new functionality as displayed below.
/**
* Constructor
*
* @param mixed $options
* @return void
* @todo add file_exists, and some validation of its content
*/
public function __construct($options = null)
{
if(defined('FORM_DECORATORS_INI')){
$ini = new Zend_Config_Ini(FORM_DECORATORS_INI);
$this->_decoratorSettings = $ini->toArray();
// set decorators for the form itself
$this->setDisableLoadDefaultDecorators(true);
$this->setDecorators($this->_getDecoratorSettings('form'));
}
// instantiate the parent class
parent::__construct($options);
}
/**
* Add an element to this form
*
* Uses $_decoratorSettings when set for the $element
* and the $options array does not contain them
*
* @see Zend_Form#addElement($element, $name, $options)
*/
public function addElement($element, $name = null, $options = null)
{
// get decorators from ini if not set in definition
if(false === isset($options['decorators'])
&& null !== $this->_decoratorSettings)
{
$decoratorSettings = array();
$decoratorSettings['decorators'] = $this->_getDecoratorSettings($element);
$options = (is_array($options) ? $options : array());
$options = array_merge($options, $decoratorSettings);
}
// call parent to do adding
parent::addElement($element, $name, $options);
}
That’s basically it. Now I can use addElement as I am used to and define my forms as desired. For we will always have to define our forms but now I don’t have to fuss with the appearance of the elements trough setting of the decorators in the options, which I think don’t belong in the form definition. But If I want to define them, I can. So even if I want to set different decorators than the ones I defined as default I can.
// add element without having to set decorators
$this->addElement('text','textinput1',array(
'label' => 'textinput 1',
'required' => true
));
This solution has proven to work for me in most cases. I know I will -at some point- have to write my own decorators or subclass or create new form elements. But for now this is a very workable solution.
Related download: Configure standard Zend Form Decorators
Sreknord.net is the personal web space of software engineer, Leonard Dronkers (NL). At Sreknord.net you will find interesting information about software engineering and web-development.
Software engineer, Leonard Dronkers is currently working as a web-developer at VNU Media (NL).
To get in touch with Leonard, please use the contact form.