With the preview release of Zend Framework 1.5 now out and things looking good for a General release in late February, let’s take a moment to really see what is new. This will be an ongoing series for a while to help you get an idea of what’s coming down the pipe.
Zend Form
Many developers like the model of being able to programmatically create all elements on a page. An equal number like to code the HTML separately. If you are one of the ones that like to create things in code, you are going to love Zend_Form. Zend_Form gives you all the tools necessary to create forms and form elements via PHP code. Like everything in Zend Framework, almost everything is configurable; however the defaults are probably good for most uses. Zend_Form helps you by simplifying the creation of these form elements as well as adding programmatic controls for validation, ordering, filtering, and grouping. The Zend Framework documentation contains a great Quick-Start Guide written by the component author, Matthew Weier O’Phinney that gives you the basics. To show you just how simple this is to use, here’s a quick code snippet.
<?php
$form = new Zend_Form;
$form->setAction('/resource/process')
->setMethod('post')
->setAttrib('id', 'login');
$username = new Zend_Form_Element_Text('username');
$username->addValidator('alnum')
->addValidator('regex', false, array('/^[a-z]/i'))
->setRequired(true)
->addFilter('StringToLower');
$form->addElement($username);
$password = new Zend_Form_Element_Password('password');
$password->addValidator('stringLength', false, array(6))
->setRequired(true)
$form->addElement($password);
$form->addElement(new Zend_Form_Element_Submit());
You can begin to get a feel for how this works from that snippet and how simple it is to build not only simple but really complex forms. I’ve listed the verbose version above so that you can see the granularity of control you have; here is the sparse version.
<?php
$form = new Zend_Form(array(
'action' => '/user/login',
'method' => 'post',
'elements' => array(
'username' => array('text', array(
'validators' => array(
'alnum',
array('regex', false, array('/^[a-z]/i')),
array('stringLength', false, array(6, 20))
),
'required' => true,
'filters' => array('StringToLower')
)),
'password' => array('password', array(
'validators' => array(
array('stringLength', false, array(6))
),
'required' => true,
)),
'submit' => 'submit',
),
));
You will notice that in this version everything is defined in an array and just handed to Zend_Form. If you work with Zend Framework at all you know that if it’s an array, it can most likely be a config. Zend_Form is no exception. It can take a Zend_Config as a parameter instead of an array. This allows you to define your form in an INI file. If we were creating our login form via a Zend_Config, the INI would look like this.
[development]
; general form metainformation
user.login.action = "/user/login"
user.login.method = "post"
; username element
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"
; password element
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true
; submit element
user.login.elements.submit.type = "submit"
To implement this you simply instantiate your Zend_Config() and then your form:
$config = new Zend_Config_Ini('/path/to/config.ini', 'development')
$form = new Zend_Form($config->user->login);
You can see the complete example, including a controller that uses it not only to display the form but also to validate the results, on the documentation page.
As I said before, some developers prefer to develop like this and others don’t. Those who prefer this method will rejoice with singing and dancing because this is a very nice implementation. It is flexible enough to be used for complex forms but the syntax is simple to grasp and won’t get in the way when building simple forms.
Those who prefer to code the HTML directly have already stopped reading by now.




January 29, 2008 at 10:57 pm
This is absolutely awesome! I have been wishing for a long time for a clean way to create and validate forms programatically.
I think I’m going to go rejoice in the streets now, singing and dancing.
January 29, 2008 at 11:09 pm
I only can say one thing to the wonderful framework dev team, how said Linda Blair: "Mommy tell him to stop!", you kill me boys, now i will forget the HTML at last.
God bless you!!
January 30, 2008 at 5:01 am
That’s a great helper and thanks for this example, especially the part using an INI file.
Is there an easy way to add a fieldset?
January 30, 2008 at 12:58 pm
@dinaboff: You can create a DisplayGroup to group elements; by default,
DisplayGroups are rendered in fieldsets. To create a DisplayGroup, use the
addDisplayGroup() method, and pass it an array of elements to group; you
also need to pass it a name, and, optionally, some configuration options:
$form->addDisplayGroup( array('login', 'password'), 'loginDetails', array('legend' => 'Login Details') );Read the manual — there’s plenty of information on Zend_Form already
documented.
January 30, 2008 at 1:29 pm
Can someone explaint he benefit to storing the form as an ini file or zend_config object? I can’t see the advantage if I’m honest. Why not just store the array in an include or the like?
January 30, 2008 at 3:22 pm
@sicouk: The benefit of storing a form configuration in a config file is
simply for creating a re-usable form (and that’s only one way to create
re-usable forms; you can also subclass).
Many people like to use configuration files in their applications. It allows
them to perform a poor-man’s dependency injection, and also allows
less-savvy developers to modify portions of the application without needing
to touch the code. Regardless, using a config file is optional; Cal
merely presents it as one available option for working with Zend_Form.
And, in case you weren’t aware, one way you can create a Zend_Config is from
a PHP file that returns an array:
You could also simply pass the array directly to Zend_Form’s constructor; it
can utilize either an array or a Zend_Config object.
January 30, 2008 at 7:13 pm
Thanks for the great example! It’s made everytyhing so clear, but where do I save the files to get it working? Is it a controller file etc? Thanks!
January 31, 2008 at 6:30 am
I very much like the elegance of the form class in terms of it syntax but making the controller actions dependent on a form is something I don’t like.
Forms are a part of the display logic – Views – and IMO they should be constructed in Views rather than make a mess in the Controllers.
But then may be I am from a different world
January 31, 2008 at 12:39 pm
Indeed great, been waiting for a feature like this for a long time. Making forms with PHP and HTML can get messy and this will definitely help clean things up.
January 31, 2008 at 5:04 pm
@Steve Smith: the config files go wherever you normally store your config
files, and you would load them accordingly. Additionally, you don’t need to
use configs at all — for your first experiments, try just programattically
creating the form and element objects.
January 31, 2008 at 5:18 pm
@tariquesani: The controller actions are not dependent on a form,
controllers simply utilize forms as they would any other objects. But you
have a point regarding mixing display logic with controllers; however,
ultimately, it’s moot, as I’ll explain below.
If you look at the goals for Zend_Form, they include:
Forms are not just display logic. When creating a typical form,
you’re thinking about how to validate the fields submitted and filter the
submitted data. Zend_Filter_Input can handle this end easily.
However, the other part of the equation, rendering, is display
logic, and that has a whole additional set of issues: how do you inject
submitted values into the form input when re-displaying a failed form
submission? How do you place the error messages? How do you i18n-ize labels
and error messages?
If you create your HTML markup by hand, you’re now having to juggle a ton of
view variables — or at the minimum a large array of items. And where does
this information come from — how is it built? Creating well-crafted forms
is a time-consuming and repetitive task.
Now, you’ll probably be happy to find that the actual rendering
logic for Zend_Form is actually separated into a different set of
classes. To a large extent, Zend_Form is its own mini-MVC layer, separating
the tasks of validation, filtering, and rendering (or, to use Zend_Form
terms, decoration) into discrete domains. Rendering is taken care
of via Decorators, and you can customize the display logic any way you want
with these.
And, to be honest, you can also simply omit them, and send your form object
to your view script, and use the elements it contains to help build your
markup by hand. Best of all worlds.
February 1, 2008 at 2:18 pm
The encapsulation provided by Zend_Form is just another reason why I am in love with the framework. Sure, I could spend endless time in escaping and writing validation methods and etc etc etc for a simple form, or learn, god forbid, smarty template programming, eek, but this gives developers a direct API to forms, and I say bring it on, the more html we can do programatically is better. It’s all about not reinventing the wheel.
Great work guys.
February 1, 2008 at 3:00 pm
Don’t want to boast, but I’ve implemented similar idea about 3 years ago. The major difference is that form configuration was described in custom XML format. Here’s example:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<form name="f_listing" datasource="tr_listing">
<input type="hidden" name="listing_seen" value="1"/>
<input type="hidden" name="is_service" value="0"/>
<input type="hidden" name="id" identity="true"/>
<input type="hidden" name="client_id"/>
<input type="text" name="ref_id" label="Ref Id" required="true"/>
<input type="hidden" name="status"/>
<input type="checkbox" name="featured" label="Featured"/>
<input type="hidden" name="rent_sale" value="2" required="true">
<option value="1" name="For Rent"/>
<option value="2" name="For Sale"/>
</input>
<input type="list" name="type_id" label="Property Type" required="true">
<query value="SELECT id,value FROM tr_listing_type WHERE is_service = 0"/>
</input>
</form>
IMO this is much more compact way.
February 1, 2008 at 4:03 pm
Hi
How to place all inside a MVC, whish part would be on the controller, and on the view using there rendered html form or using the array for templates?
February 2, 2008 at 6:52 pm
Nice job with the Zend_Form module. All my respect to the author and I hope he will continue his work in the future.
I have been using Zend_Filter_Input for custom chaining validation but I will switch to Zend_Form.
Aren’t this 2 components (Zend_Form and Zend_Filter_Input) stepping on eachouther toes right now? Looks like it, since Zend_Form is not using Filter_Input for it’s chaining validation.
February 8, 2008 at 3:59 pm
@deusx: I see Zend_Filter_Input and Zend_Form as serving different purposes.
Zend_Form does not use Zend_Filter_Input internally as validation and
filter chains are done per element; Zend_Filter_Input is geared
towards collections. What this means is that with Zend_Form, you
can validate a single element at a time if you want, or even partial sets of
data (for instance, in AJAX requests) – something that Zend_Filter_Input is
not really geared for. This feature of Zend_Form also allows you to re-use
individual elements across multiple forms, another trick that would be
difficult for Zend_Filter_Input. However, note that both use
Zend_Validate and Zend_Filter for their chains.
Additionally, I see the two as responsible for separate arenas.
Zend_Filter_Input is a great choice for use in your model classes, as it
allows you to validate data passed to your model and filter it for the model
storage mechanism. This is particularly useful when writing models that you
then attach to servers such as Zend_XmlRpc_Server and Zend_Rest_Server.
Zend_Form is geared more towards application logic — i.e., gathering input
to provide to models, as well as collecting items that should be
displayed to the user for action. Items in Zend_Filter_Input may
never be displayed, but may come from other sources.
Finally, Zend_Form implements something Zend_Filter_Input does not do
currently: it implements a plugin architecture to allow easily and simply
specifying validators and filters, and providing for replacements of
standard components.
February 8, 2008 at 4:04 pm
@chelala: I personally subclass my forms, and then all I need to do is the
following in my controller actions:
$request = $this->getRequest(); $form = new My_Form_Login(); if (!$request->isPost()) { $this->view->form = $form; // renders view script return; } if (!$form->isValid($request->getPost())) { $this->view->form = $form; // renders view script; form now has values and error messages return; } // success! $values = $form->getValues(); $model->save($values); $this->_redirect(...);In your view script, to render the form, you simply do:
Basically, the MVC usage does not differ much from the standard procedural
usage.
March 18, 2008 at 4:25 pm
it’s convenient to have that form. it looks similar to the drupal one. Why don’t we make some set methods for form’s attributes instead of that messy array?
March 18, 2008 at 4:29 pm
sorry sorry… I only looked at the one with array, didn’t see the above one. That’s what I mean what it should have. Zend is great!
May 30, 2008 at 1:48 pm
Is it possible to autoload my own /path/to/a/set/of/validators? Without having to extend the elements, or passing the prefixpath to every new form object.
Ty.
June 29, 2008 at 10:33 pm
Looks like a very usable system! And its always nice to use your own stuff, you know how everything works, etc.
Zend form is very nice, and for me is an end-all formclass, especially with the translation that make multi-lingual sites very easy to manage. I use Zend_Translate with po-files edited on "pootle" translation manager. Highly recommended!
January 12, 2009 at 4:32 pm
I am currently using this in a project I am working on
This located in library/Ca/Form/Default.php
<code>
<?php
class Ca_Form_Default extends Zend_Form
{
public $login;
public function deafultforms($login)
{
$fname = $this->createElement(
‘text’, ‘fname’, array(
‘label’ => ‘First name:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
‘Alpha’
)));
$lname = $this->createElement(
‘text’, ‘lname’, array(
‘label’ => ‘Last name:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
‘Alpha’
)));
$city = $this->createElement(
‘text’, ‘city’, array(
‘label’ => ‘City:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
‘Alpha’
)));
$state = $this->createElement(
‘text’, ‘state’, array(
‘label’ => ‘State:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
‘Alpha’
)));
$zip = $this->createElement(
‘text’, ‘zip_code’, array(
‘label’ => ‘zip code:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
array(‘regex’, false, ‘/^[0-9\-]/i’)
)));
// add username element
$username = $this->createElement(
‘text’, ‘username’, array(
‘label’ => ‘Username:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
array(‘regex’, false, ‘/^[a-zA-Z0-9_]/i’)
)));
// add an email element
$email = $this->createElement(
‘text’, ‘email’, array(
‘label’ => ‘Your email address:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
‘EmailAddress’
)));
// add element password
$password = $this->createElement(
‘password’, ‘password’, array(
‘label’ => ‘Password:’,
‘required’ => true,
‘filters’ => array(‘StringTrim’),
‘validators’ => array(
array(‘regex’, false, ‘/^[a-zA-Z0-9]/i’)
)));
// add element captcha
$captcha = new Zend_Form_Element_Captcha(
‘captcha’, array(
‘captcha’ => array(
‘captcha’ => ‘Image’,
‘wordLen’ => 6,
‘timeout’ => 300,
// BASEURL defined in index.php
‘imgUrl’ => BASEURL . ‘images/captcha’,
‘width’ => 200,
‘height’ => 60,
‘font’ => ‘/var/www/html/zends/zendspace/img/captcha/Activa.ttf’
)));
// AdminInterface Form Elements
// to be written
// UserInterface Form Elements
// to be written
$dlogin = array($username, $password, $captcha);
$dreg = array($fname, $lname, $city, $state, $zip, $username, $password, $email, $captcha);
if($login == ‘login’){
return $this->addElements($dlogin);
}elseif($login == ‘reg’){
return $this->addElements($dreg);
}
}
}
</code>
It’s very sparse for validators and filters, basically because I am still learning. I basically would like to use a class like this because of KISS. If I ever want to change anything I just go to this class and change what I need. My question is am I on the right path and if not any guidance would be appreciated.
Thanks,
Dave
February 13, 2009 at 10:46 pm
Very good post.
I do have a question. I already have my elements created in an ini file with the validations in place.
my confusion is how to be able to have those work from inside my action methods?
ex.
i have a
public function infoRequestPostAction() {
if ($this->getRequest->isPost()) {
//validate elements
}
}
something like that
any guidance would be \m/>.<\m/
March 17, 2009 at 6:10 pm
"You can see the complete example, including a controller that uses it not only to display the form but also to validate the results, on the documentation page."
Why couldn’t you just provide the link? I can’t find it!!!
http://devzone.zend.com/article/3030-Lifting-the-Skirt-on-Zend-Framework-1.5—Zend_Form
April 23, 2009 at 8:41 pm
I know this is the simplest way of making forms.
But actually forms are not that simple – it will have things like, Field Info, Icons etc
For example a message just above the Text Area in your Blog [Total words should be more than 500 characters and less than 2000 characters]
or you may need to graphically show how secure is the password or length of password etc.
So, under such circumstances, which one will you prefer.
July 14, 2011 at 6:19 am
I have created form in config/form.ini
————–form.ini—————————-
[development]
; general form metainformation
user.login.action = "/user/login"
user.login.method = "post"
; username element
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"
; password element
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true
; submit element
user.login.elements.submit.type = "submit"
——————-End Form————————————
Then i place the below code in User Controller
—————-User Controller——————————–
$formConfig = new Zend_Config_Ini(APPLICATION_PATH.’/configs/form.ini’);
$newUserForm = new Zend_Form($formConfig);
$this->view->newUserForm = $newUserForm;
——–End USer Controller————————————-
then place the below code in view/login.phtml
———–Login.phtml—————————————–
echo $this->newUserForm;
——————-End Login.phtml—————————-
now i try to run
http://localhost/user/login
nothing display except my layout. kindly guide me where went wrong?
July 14, 2011 at 1:41 pm
It’s how you’re grabbing your configuration. Use the following:
// Make sure you grab the "development" section, as that’s where you defined the configuration
$formConfig = new Zend_Config_Ini(APPLICATION_PATH . ‘/configs/form.ini’, ‘development’);
// Make sure you grab the appropriate part of the form configuration — which you namespaced at "user.login"
$newUserForm = new Zend_Form($formConfig->user->login);
July 14, 2011 at 5:16 pm
thank u..now its working fine…..