Tecnologia -> Linguagem -> PHP -> Simple Zend_Form Example

Simple Zend_Form Example

Following on from the Simple Zend_Layout Example, Zend_Form is now in the trunk, so here's a super simple, complete example that shows it in action:
Zend_Form screenshot1.png
(clearly the form is unstyled :)
You can construct a Zend_Form directly from a config file or can build it in code. This example builds it in code.

Setting up

This example uses the same basic skeleton as the Zend_Layout code with the addition of a forms directory:
Zend_Form Directory Layout.png
As you can see, I've added a forms directory within the application subdirectory with our form file, ContactForm.php, in it.

The contact form

To keep the form contained, I've put it in its own class which extends from Zend_Form. The file is application/forms/ContactForm.php and so the class is forms_ContactForm so that Zend_Loader can easily load it:

class forms_ContactForm extends Zend_Form { 
    public function __construct($options null) 
    { 
        parent::__construct($options);
        $this->setName('contact_us');
        
        $title = new Zend_Form_Element_Select('title');
        $title->setLabel('Title')
              ->setMultiOptions(array('mr'=>'Mr''mrs'=>'Mrs'))
              ->setRequired(true)->addValidator('NotEmpty'true);
        
        $firstName = new Zend_Form_Element_Text('firstName');
        $firstName->setLabel('First name')
                  ->setRequired(true)
                  ->addValidator('NotEmpty');

        $lastName = new Zend_Form_Element_Text('lastName');
        $lastName->setLabel('Last name')
                 ->setRequired(true)
                 ->addValidator('NotEmpty');
             
        $email = new Zend_Form_Element_Text('email');
        $email->setLabel('Email address')
              ->addFilter('StringToLower')
              ->setRequired(true)
              ->addValidator('NotEmpty'true)
              ->addValidator('EmailAddress'); 
              
        
        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setLabel('Contact us');
        
        $this->addElements(array($title$firstName, 
            $lastName$email$submit));
        
    } 
}
We set the name of the form first and then create five elements; one select box for the title, three text boxes for first name, surname and email address and then finally a submit button. Note that as we have overridden the constructer, we also call up to the parent's constructor so that all the Zend_Form initialisation happens.
Creating an element is quite simple. Each element is of the type Zend_Form_Element_Xxx where Xxx is the type, such as Text, Submit, Select, etc. We then configure the element how we want it, such as setting a label and adding filters and validators. Finally we add all the elements to the form using the addElements() function.
Note that if you have multiple validators, you can pass in true as the second parameter ($breakChainOnFailure) to stop processing the remaining validators at that point. This can be because the further validators do not make sense or because you only ever want the user to see one message per field to avoid overwhelming them.

Displaying the form

Having defined out form, we need to get it to the screen. In the controller we need the following:

class IndexController extends Zend_Controller_Action{
    function indexAction()
    {
        $this->view->pageTitle "Zend_Form Example";
        $this->view->bodyCopy "Please fill out this form.";

        $form = new forms_ContactForm();
        $this->view->form $form;
    }
}
This code assigns some variables to the view, then instantiates the form and assigns that to the view also. The view script is similarly simple:
view/scripts/index/index.phtml:
echo $this->pageTitle ;?>
echo $this->bodyCopy ;?>
echo $this->form ;?>
To render the form, we simply echo it. By default, the form is marked up as a definition list and its HTML looks like this:

<form name="contact_us" id="contact_us" enctype="application/x-www-form-urlencoded" action="" method="post"><dl class="zend_form">
<dt><label for="title" class="required">Titlelabel>dt>
<dd>
<select name="title" id="title">
    <option value="mr" label="Mr">Mroption>
    <option value="mrs" label="Mrs">Mrsoption>
select>dd>
<dt><label for="firstName" class="required">First namelabel>dt>
<dd>
<input type="text" name="firstName" id="firstName" value="">dd>
<dt><label for="lastName" class="required">Last namelabel>dt>
<dd>
<input type="text" name="lastName" id="lastName" value="">dd>
<dt><label for="email" class="optional">Email addresslabel>dt>
<dd>
<input type="text" name="email" id="email" value="">dd>
<dt>dt><dd>
<input type="submit" name="submit" id="submit" value="Contact us">dd>dl>form>
Notice how the setRequired() has resulted in the "required" CSS class name being applied to those elements.

Decorators

If you do not want to use a definition list, then this can easily be changed using decorators. For instance, adding the following to the bottom of the form's constructor after the addElements() call:

        $this->clearDecorators();
        $this->addDecorator('FormElements')
         ->addDecorator('HtmlTag', array('tag' => '
    '))          ->addDecorator('Form');                  $this->setElementDecorators(array(             array('ViewHelper'),             array('Errors'),             array('Description'),             array('Label', array('separator'=>' ')),             array('HtmlTag', array('tag' => 'li''class'=>'element-group')),         ));         // buttons do not need labels         $submit->setDecorators(array(             array('ViewHelper'),             array('Description'),             array('HtmlTag', array('tag' => 'li''class'=>'submit-group')),         ));
will result in the form being marked up as an unsigned list with each label and element pair inside each
  • . The marked up form looks like this:
    
    <form name="contact_us" id="contact_us" enctype="application/x-www-form-urlencoded" action="" method="post"><ul>
    <li class="element-group"><label for="title" tag="" class="required">Titlelabel> 
    <select name="title" id="title">
        <option value="mr" label="Mr" selected="selected">Mroption>
        <option value="mrs" label="Mrs">Mrsoption>
    select>li>
    <li class="element-group"><label for="firstName" tag="" class="required">First namelabel> 
    <input type="text" name="firstName" id="firstName" value="">li>
    <li class="element-group"><label for="lastName" tag="" class="required">Last namelabel> 
    <input type="text" name="lastName" id="lastName" value="">li>
    <li class="element-group"><label for="email" tag="" class="required">Email addresslabel> 
    <input type="text" name="email" id="email" value="">li>
    <li class="submti-group"><input type="submit" name="submit" id="submit" value="Contact us">li>ul>form>
    As you can see, the decorator system makes it easy to render our form in the manner we wish. As a note of warning, pay attention to the order of the decorators as it matters!

    Processing

    The form is now displayed, so when the user presses the button we need to process it. In this example, this is done in the indexAction() controller function, so that the complete function looks like this with the addition in bold:
    
    class IndexController extends Zend_Controller_Action{
        function indexAction()
        {
            $this->view->pageTitle "Zend_Form Example";
            $this->view->bodyCopy "Please fill out this form.
    "
    ;         $form = new forms_ContactForm();         if ($this->_request->isPost()) {             $formData $this->_request->getPost();             if ($form->isValid($formData)) {                 echo 'success';                 exit;             } else {                 $form->populate($formData);             }         }         $this->view->form $form;     } }
    Firstly we check the the request is a POST using the request object's isPost() function and then we use validate the submitted data using the form's isValid() function. If this returns true, then we have valid data and can process. If the data is not valid, we populate the form's elements with it and then redisplay so that the user can correct appropriately. The default decorators will display an error message next to each element that failed validation.

    Conclusion

    So there you have it. A very simple example of how to use Zend_Form.
    Here's a zip file of this project: Zend_Form_Example.zip (It includes a snapshot of the trunk of the Zend Framework which is why it's 3MB big.)
    It works for me, at least.

    Update

    With the release of Zend Framework 1.5, a change was made to the way buttons work and you should not put a label decorator on a button as the label property of a button is used for the text value of the button itself.
    I have updated the code above to show that if you use setElementDecorators() you then need to reset the decorators for any buttons, the $submit button, in this case. I have also put back the Errors decorator when using an unsigned list.