Forms in Zend Framework
I’m often asked what my favorite component of Zend Framework is, and I invariably answer: “Forms”. Forms have always played an awkward role in the model-view-controller paradigm. Sure, the form is just HTML, but to me, it represents something more abstract than that. It represents the HTML form itself, taking user input, normalizing and validating it, and also being able to show the form again when errors occur. This can take quite a large amount of code.
If you’re able to automate all of that stuff, then all you are really left with is configuration. Each form consists of elements, and each element has several attributes which modify the overall functionality of the form. Let’s look at some of these aspects.
Defining a Form
A form itself is an instance of Zend_Form. There are many ways to define one. I prefer to extend Zend_Form for each of my forms, and define them inside the class itself. Each form contains a few important fields (action, method) and also it contains at least one element. Let’s look at how we define an element. Each element probably has a few common attributes: a field type, a label, an element name, and a description. Let’s represent this element in ZF. Note, there are several different ways to represent forms. They can literally be done via configuration, or by a few different PHP methods. This is my favorite.
$username = new Zend_Form_Element_Text('username', array(
'label' => 'Username',
'description' => 'This is a description'
));
In the above code, you can see we define these three things. There are also some other important attributes for elements. Let’s add a few more, and show a few fields at once.
$this->addElements(array(
new Zend_Form_Element_Text('username', array(
'label' => 'Username',
'required' => true
)),
));
Filters and Validators
One very helpful feature with the forms component is the ability to chain filters and validators. A filter is something that automatically manipulates incoming data to your desired format, and a validator is something that is checked when processing the form. This greatly simplifies your controller code, and your model code, because you are shifting all of this logic into a much more organized structure.
For example, if you are working with a username element on a registration form, then you may want check that the user does not already exist, the username does not contain any illegal characters, and the username is within a desired length.
If you had an element where the user can enter a few paragraphs about himself, then you would want to apply some filters to make sure the data is clean. You may want to add things like StripTags to remove any HTML, StringTrim to remove any extra whitespace, etc. You could also apply some custom BBCode parsing filters if you wanted. You could create your own filter for this, or use the Callback filter which you can use for everything else.
The idea is to do as much validation as possible so you know that your data is 100% ready for your application. If you have a VARCHAR(255) field, then limit your string to 255 characters so nothing gets truncated. Be very strict.
Filters are more of a time saver to me… but they are nice because they help keep all the data very consistent or can also be part of your cleaning process. If you are allowing user input, then remove any HTML is necessary. You get the idea.
Here is a more complete example of a registration form definition:
$this->addElements(array(
new Zend_Form_Element_Text('username', array(
'label' => 'Username',
'required' => true,
'validators' => array(
array('StringLength', false, array(4, 16)),
array('Alnum'),
array('Db_NoRecordExists', false, array('users', 'username'))
)
)),
new Zend_Form_Element_Text('email', array(
'label' => 'Email Address',
'required' => true,
'validators' => array(
array('EmailAddress'),
array('Db_NoRecordExists', false, array('users', 'email'))
)
)),
new Zend_Form_Element_Password('password', array(
'label' => 'Password',
'required' => true
))
));
Skinny Controller, Fat Model
With a form containing the fields above, we can really simplify our controller code. To me, controller’s should contain the flow of an application, without really performing any of the work. Here is an example of a registration action.
if ($this->_request->isPost()) {
if ($form->isValid($this->_request->getPost())) {
$user->register($form->getValues());
$this->redirector->goToUrl('/welcome');
}
}
$this->view->form = $form;
If the user has submitted (posted) any information, then the form validates that posted information. If it’s valid, it will proceed to pass the data array to our model. At this point, all of our filters and validators have been executed, so we know exactly how the data is formatted, and that it’s safe to use. We can proceed to redirect the user away, or perform any other flow logic we need to at this point.
We also pass the form to the view, which is crucial. On a regular page view, the form will be loaded normally. On a failed submission, then it will show the form with all of the error messages, and the posted data populated back into the form elements.
View Scripts & Decorators
Here is all the code we need in our view to show a form. The rest can be done via CSS, or custom decorators if we need it.
<?= $this->form ?>
By default, Zend_Form outputs a pretty usable chunk of HTML. I have no problems styling it via CSS which is really great for our separation of concerns. However, there will be times when you need markup in certain format, and Zend can handle this with decorators. They are a little tricky to learn, so I will save that for another blog post. There should be sufficient documentation on their website.
Dealing with Models
As per our controller code, the model would receive $form->getValues(), which would be a pre-validated and pre-filtered array of our data. Here is an example:
// ...
public function register(array $user) {
}
// ...
To me, this is beautiful. We are working with a very basic interface, and do not have to manually specify every value that we pass or expect. While this is personal taste, I cringe whenever I see people pass 5-10 values to a model. Their controllers all end up being huge. The code is also not dependent on our form, because it’s just dealing with an array of data. It makes calling our models very simple, too. The model is where the code should start to get complicated. From this point, we can use our database adapter object, or deal with several other libraries.
Summary
The form component is one of the larger (largest?) components in Zend. Don’t be afraid to ask for help on the different forums, or ask below and I can point you to a good resource. Like I said above, this is the most useful component in Zend to me, so if you are considering taking the time to learn how to use it, I strongly advise to do so.
You may also be interested in caching forms.

I also like to pass form as parameter to model.
I like that too… very simple. I guess it depends on whether or not you want the extra dependency in your models. In most cases it should be fine.
Hi Adrian,
Very nice and simple article! I just want to get an opinion from you that how easy/hard is it when you work with designers to carry out fancy and complex forms?
I used Zend_Form in my ZF projects at the start, but I just found it’s becoming too hard to catch up with all the UI requirements, and also nested forms that potentially deal with multiple models …
How do you deal with these kind of situations?
Hi Jim,
Thanks for the kind words. Basically there are two ways to tackle the situation:
1) Use decorators + CSS. Custom decorators can be a little tricky to understand, but it works most of the time. If you can look at your forms and see common patterns, then odds are this will work.
2) Don’t use them at all. You can actually directly render elements into the view scripts and not render the whole form. For example: <?= $form->elementName-> ?> . You can access everything you need to this way, and can completely bypass the decorators.
I haven’t had much experience or need with nested forms or subforms to be honest, so I can’t really help you there. I’d take specific examples over to the forums and try to get help that way. However, dealing with multiple models shouldn’t be an issue. It’s up to you to figure out how to handle the data once it comes out of the form.
Hope this helps.
Hi Adrian,
The constant battle is that the designer wants to make things pretty, but they cannot and should not get to the model class code … That’s why at the moment I’m only using Zend_Form for data filtering, validation. and I had to manually make the form in plain HTML … it’s a pain when you need to make a change … since it’s not DRY enough, you have to go 2 different places … the form model then the view script …
I think I’l give your option 2 a go.
Thanks!
I’m kinda with Jim on this one; We used Zend on one of our recent projects. My opinion of the form component was good at first, but lateron I foundation that the default html output is far from semantic. I think a dl is not ment for forms. With my little experience in ZF I managed to get everything the way I wanted, but it took a lot of effort.
So I’m sorry to say that I don’t really share your enthousiasm. Other than that: good post! I’ll keep following your website
I agree with the DL comment. However, I dodge that argument usually as I leave it up to front-end developers that I work with to choose how they want to do it. I know setting up the decorators is a pain, but once you do it, it can be easily transferred to your future projects.
Don’t feel bad though, if everybody had the exact same opinions then I’m pretty sure our lives would suck. It has worked well for me, and that’s all I care about. However, it’s great when people at least try new things and not live with tunnel vision.
Cheers, and many more posts to come.
An excellent article. Thank you.
I have translated it to Russian.
http://www.smartyit.ru/zend-framework/79
For those looking for some help with decorators, a new screencast was posted over at zendcasts.com
http://www.zendcasts.com/zend_form-decorators-explained/2010/02/
I agree with the other commenters: that the concept of forms is well thought out in theory, but implementing can be a nightmare – try and validate multiple form elements together (for example, you need a customer validator to check a combination of elements in a database), the code just starts getting large and messy.
The decorators – again – pain in the a*** !! For starters there seems to be 3 or 4 different ways of customising the form, no real definitive answer on how you should do it, and it’s not until your half way down the road you realised you picked the wrong option.
To put the onus on the front-end developer to have to rebuild a decorator everytime is not praticle.
Yes – “you only have to do it once” if you in the position where you can reuse your code lib, but that’s not always possible (and I hate copy-paste code libs,etc.)
Still, in reflection, I think that the forms in ZF are getting better, well, the documentation around them are, and blogs like this really help – thanks (when I started out with ZF forms, there was virtually nothing).