Zend Framework forms, decorators and validation: should I go back to plain HTML?

Aron Rotteveel picture Aron Rotteveel · Aug 14, 2009 · Viewed 7.6k times · Source

I am currently working on a pretty large application which contains a lot of forms.

Up to this moment, I have always been writing my forms by hand and writing my own validation logic, but I have decided it was about time I started using Zend_Form and it's built-in validation routines.

However, I keep stumbling upon more and more problems concerning the (lack of) flexibility caused Zend_Form_Decorator. Simple tasks like adding an extra button to a single input-element become incredibly difficult tasks.

I have now reached a point where I am seriously considering dropping the Zend_Form_Element + Zend_Form_Decorator approach entirely, but I do not want to lose the excellent validation options.

Basically, I want the best of both worlds:

  • Write forms the way the end-user sees them: in plain HTML
  • Easily add server-side validations to form fields without breaking too much of the ZF standard behaviour

A possible solution I am considering is writing the forms both on the server side as in the views. This would allow me to easily validate my own forms, but the (in my eyes quite big) downside is that each form should be defined twice, which just feels plain wrong.

Are there any guidelines to do this? Have any of you experienced the same, and if so, how have you solved these issues?

I'd very much like to hear your points of view.

Answer

Cal Jacobson picture Cal Jacobson · Aug 14, 2009

I too find the default decorators to be a massive pain. I understand why they are the way they are, but I think the 'inconvenience factor' has been grossly underestimated.

Anyway, I would recommend using ViewScripts for your forms. Note that these are not the same as Views -- instead, ViewScripts are referenced explicitly in your Form class, act as a "sub-view" of sorts and allow you to control the layout of each and every element. Examples how to use ViewScripts have been somewhat hard to find in the past, but I'll try to take a stab at providing something useful.

First, override loadDefaultDecorators in your form class:

public function loadDefaultDecorators() {
     $this->setDecorators(
         array(
             array('ViewScript', 
                 array('viewScript' => 'foo/bar.phtml')
             )
          )
      );        
} 

This will reference a ViewScript named bar.phtml located in /views/scripts/foo. Note the case-sensitive differences in "ViewScript" and "viewScript" above.

Next, you'll have to tweak the decorators applied to each element to ensure it displays but without the annoying dt/dd wrappers. For instance:

$baz = new Zend_Form_Element_Text('bazInput');
$baz->setDecorators(array('ViewHelper','Errors')); 

Finally, you'll need to build your ViewScript, such as:

<form method="post" action="<?php echo $this-element->getAction() ?>">
    <table>
        <tr>
            <td><label for="bazInput">Baz:</label></td>
            <td><?php echo $this->element->bazInput ?></td>
        </tr>
    </table>
    <input type="submit" value="Submit Form" />
</form>

Obviously this is a very simple example, but it illustrates how to reference the form elements and form action.

Then in your View, simply reference and output your form as usual. This way you can have much finer control over your form layouts -- to include easily adding Javascript.

I believe this approach resolves both your requirements: you can build forms in plain HTML and still take advantage of the Zend Form validation mechanism.