A web developer's blog. PHP, MySQL, CakePHP, Zend Framework, Wordpress, Code Igniter, Django, Python, CSS, Javascript, jQuery, Knockout.js, and other web development topics.

Zend Framework Tutorial: A Fully Customized Form Using Zend_Form and Decorators (UPDATED now using Tables)

This tutorial is derived from this post. So I suggest that you read weirophinney’s post first before this.

This method of rendering a form can be more verbose, but it also allows you to tweak the form at almost infinitely whole still gaining the advantages of error reporting, labeling, etc that decorators provide (by using the decorators associated with the elements).

I would like to stress out the advantages:

  • Error Reporting
  • And Labelling

You get these by doing only this in your view script (.phtml file):

<?=$this->form->firstname ?>
<?=$this->form->lastname ?>

Looking good? Well, here is the rest of it.

First, create this file: application/forms/sample/sampleform.php

Inside sampleform.php, you should have something like this:

 class forms_sample_sample2form extends Zend_Form
{
    public $checkboxDecorator = array(
                                    'ViewHelper',
                                    'Errors',
                                    'Description',
                                    array('HtmlTag',array('tag' => 'td')),
                                    array('Label',array('tag' => 'td','class' =>'element')),
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
    public $elementDecorators = array(
                                    'ViewHelper',
                                    'Errors',
                                    'Description',
                                    array('HtmlTag',array('tag' => 'td')),
                                    array('Label',array('tag' => 'td','class' =>'element')),
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
    public $buttonDecorators = array(
                                    'ViewHelper',
                                    array('HtmlTag',array('tag' => 'td')),
                                    //array('Label',array('tag' => 'td')), NO LABELS FOR BUTTONS
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
    public function init()
    {
        $this->setAction('');
        $this->setMethod('post');
 
        $this->addElement('text', 'email', array(
            'decorators' => $this->elementDecorators,
            'label'       => 'Email:',
            'required'   => true,
            'validators'  => array(
                            'EmailAddress',
                            ),
            'attribs' =>   array(
                                'id'=>'email_id',
                                'class'=>'email_class'
                            ),
        ));
 
        $this->addElement('text', 'age', array(
            'decorators' => $this->elementDecorators,
            'label'      => 'Age:',
            'required'   => true,
        ));
 
        $this->addElement('select', 'country', array(
            'decorators' => $this->elementDecorators,
            'label'      => 'Country:',
            'required'   => true,
            'attribs' =>   array(
                                'id'=>'country_id',
                            ),
            'multioptions'   => array(
                            'ph' => 'Philippines',
                            'us' => 'USA',
                            ),
        ));
 
        $this->addElement('text', 'username', array(
            'decorators' => $this->elementDecorators,
            'label'       => 'Username:',
            'validators'  => array(
                                array('stringLength', 1, 255)
                            ),
            'required'   => true,
        ));
 
        $this->addElement('text', 'firstname', array(
            'decorators' => $this->elementDecorators,
            'label'      => 'First Name:',
            'required'   => true,
        ));
 
        $this->addElement('text', 'lastname', array(
            'decorators' => $this->elementDecorators,
            'label'       => 'Last Name:',
            'required'   => true,
        ));
 
        $this->addElement('radio', 'gender', array(
            'decorators' => $this->elementDecorators,
            'label'      => 'Gender:',
            'required'   => true,
            'attribs' =>   array(
                                'id'=>'gender_id',
                            ),
            'multioptions'   => array(
                            'male' => 'Male',
                            'female' => 'Female',
                            ),
        ));
 
        $checkboxDecorator = array(
                                'ViewHelper',
                                'Errors',
                                array(array('data' => 'HtmlTag'), array('tag' => 'span', 'class' => 'element')),
                                array('Label', array('tag' => 'dt'),
                                array(array('row' => 'HtmlTag'), array('tag' => 'span')),
                            ));
        $this->addElement('checkbox', 'agreement', array(
            'decorators' => $checkboxDecorator,
            'label'       => 'Agreement:',
            'required'   => true,
        ));
 
        $this->addElement('submit', 'save', array(
            'decorators' => $this->buttonDecorators,
            'label'       => 'Save',
        ));
 
    }
    public function loadDefaultDecorators()
    {
        $this->setDecorators(array(
            'FormElements',
            array('HtmlTag', array('tag' => 'table')),
            'Form',
            'Errors'
        ));
    }
}

Then inside one of my controller-action, I have this:

    public function sample2Action()
    {
        require_once  'forms/sample/sampleform.php';
        $form = new forms_sample_sampleform();
        //get the request object
        $request = $this->getRequest();
        if($request->isPost()) {
            if($form->isValid($request->getPost())) {
                //do some saves here
                var_dump($request->getPost());
            }
        }
        $this->view->form = $form;
    }

Now, in my view script. These are the .phtml files.

<h4>Please register with us!</h4>
<form action="<?= $this->escape($this->form->getAction()) ?>" method="< ?= $this->escape($this->form->getMethod()) ?>">
 
<fieldset>
    <legend>Demographics</legend>
 
        Please provide us the following information so we can know more about
        you.
 
    < ?= $this->form->age ?>
    < ?= $this->form->country ?>
 
</fieldset>
 
<fieldset>
    <legend>User Information</legend>
 
        Now please tell us who you are and how to contact you.
 
    < ?= $this->form->username ?>
    < ?= $this->form->firstname ?>
    < ?= $this->form->lastname ?>
    < ?= $this->form->email ?>
    < ?= $this->form->gender ?>
    < ?= $this->form->agreement ?
 
</fieldset>
 
< ?= $this->form->save ?>
</form>

Enjoy!

Feel free to comment/suggest… ;)

Some references in order to help you understand the form decorators ($elementDecorators, etc.) can be found in this thread from Nabble Zend Framework.

UPDATE:
The $elementDecorators variable above might seem a little bit confusing, so here is another example on how to handle it. This one sets a “class” for the first cell and the second cell of the table.

    public $elementDecorators = array(
                                    'Label',
                                    array(array('labelTd'=>'HtmlTag'),
                                          array('tag'=>'td', 'class'=>'label_cell')),
                                    array(array('elemTdOpen'=>'HtmlTag'),
                                          array('tag'=>'td', 'openOnly'=>true,
                                                'class'=>'input_cell', 'placement'=>'append')),
                                    'ViewHelper',
                                    'Errors',
                                    array('Description', array('tag' => 'div')),
                                    array(array('elemTdClose'=>'HtmlTag'),
                                          array('tag'=>'td', 'closeOnly'=>true, 'placement'=>'append')),
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
 
    public $checkboxDecorator = array(
                                    'ViewHelper',
                                    'Errors',
                                    'Description',
                                    array('HtmlTag',array('tag' => 'td')),
                                    array('Label',array('tag' => 'td','class' =>'element')),
                                    array('Description', array('tag' => 'span')),
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
 
    public $buttonDecorators = array(
                                    'ViewHelper',
                                    array('HtmlTag',array('tag' => 'td')),
                                    //array('Label',array('tag' => 'td')), NO LABELS FOR BUTTONS
                                    array(array('row' => 'HtmlTag'), array('tag' => 'tr')));
This entry was posted in General and tagged , , . Bookmark the permalink.

15 Responses to Zend Framework Tutorial: A Fully Customized Form Using Zend_Form and Decorators (UPDATED now using Tables)

  1. Gerard says:

    1. application/forms/sample/sampleform.php L95-101 Make the checkbox decorator a property.

    2. Be consistent
    sample2Action() L6-7
    $request = $this->getRequest();
    if($this->getRequest()->isPost()) {
    }

    should be

    $request = $this->getRequest();
    if($request->isPost()) {
    }

    Other than that, thanks.

  2. Wenbert says:

    Thanks Gerard. I just fixed the post.

  3. Javatuan says:

    attribs of gender is “array(‘id’=>’country_id’,)”, Should it be gender_id or something like that?

  4. Wenbert says:

    @Javatuan you’re right. It should have been gender_id. The post is now fixed ;-)

  5. markteam says:

    tnx man.it’s useful post

  6. Put says:

    Thanks dude, great work and tutorial

  7. joseph says:

    do you mind showing a bit the whole mechanism using viewscript.it’s still confusing as in, if indexAction creates the form and attached let’s say exampleviewscript.phtml to it as viewscript, what will index.phtml do in this case?this worries be bad.can anyone shed some light?

  8. Wenbert says:

    @joseph, I am not sure what you mean but the “form” is loaded in public function sample2Action() and then rendered in the respective view file.

  9. Pit says:

    great work man. Thanks sharing!

  10. bhupen says:

    class Application_Form_Album extends Zend_Form
    {
    public function init()
    {
    $this->setName(‘album’);

    $id = new Zend_Form_Element_Hidden(‘id’);
    $id->addFilter(‘Int’);

    $artist = new Zend_Form_Element_Text(‘artist’);
    $artist->setLabel(‘Artist’)
    ->setRequired(true)
    ->addFilter(‘StripTags’)
    ->addFilter(‘StringTrim’)
    ->addValidator(‘NotEmpty’);

    $title = new Zend_Form_Element_Text(‘title’);
    $title->setLabel(‘Title’)
    ->setRequired(true)
    ->addFilter(‘StripTags’)
    ->addFilter(‘StringTrim’)
    ->addValidator(‘NotEmpty’);

    $address = new Zend_Form_Element_Text(‘address’);
    $address->setLabel(‘Address’)
    ->setRequired(true)
    ->addFilter(‘StripTags’)
    ->addFilter(‘StringTrim’)
    ->addValidator(‘NotEmpty’);

    $country = $this->createElement(‘select’,'country’);
    $country ->setLabel(‘Countries:’)
    ->addMultiOptions(array(
    ‘US’ => ‘United States’,
    ‘UK’ => ‘United Kingdom’
    ));

    $gender = $this->createElement(‘radio’,'gender’);
    $gender->setLabel(‘Gender:’)
    ->addMultiOptions(array(
    ‘male’ => ‘Male’,
    ‘female’ => ‘Female’
    ))
    ->setSeparator(”);

    $address1 = new Zend_Form_Element_Textarea(‘address1′);
    $address1->setLabel(‘Address’)
    ->setAttrib(‘rows’,’4′)
    ->setAttrib(‘cols’,’20′)
    ->addFilter(‘StripTags’)
    ->addFilter(‘StringTrim’)
    ->addValidator(‘NotEmpty’);

    $submit = new Zend_Form_Element_Submit(‘submit’);
    $submit->setAttrib(‘id’, ‘submitbutton’);

    $this->addElements(array($id, $artist, $title,$address,$country,$gender,$address1, $submit));
    }

    public function addmod()
    {
    $this->setName(‘album’);

    $id = new Zend_Form_Element_Hidden(‘id’);
    $id->addFilter(‘Int’);

    $artist = new Zend_Form_Element_Text(‘artist’);
    $artist->setLabel(‘Artist’)
    ->setRequired(true)
    ->addFilter(‘StripTags’)
    ->addFilter(‘StringTrim’)
    ->addValidator(‘NotEmpty’);

    $submit = new Zend_Form_Element_Submit(‘submit’);
    $submit->setAttrib(‘id’, ‘submitbutton’);

    $this->addElements(array($id, $artist, $title,$address,$country,$gender,$address1, $submit));

    }

    }

    Having problem in above code when i run the code from controler it runs init method, but if i want to run the below method than what to do ??

    Simply want to create more form and want to call them from controller

    this code disply the form in add.phtml file

    echo $this->form ;

    what to write in addmod.phtml file ??

    Thanks !!

  11. Thank you Webnert Del Rosario for this wonderful example. I was finding the documentation in zend framework on Zend_Form quite difficult to understand but your post came to my rescue at the right time.

    Thank You once again.

    Sri Sri RadhaGopinath

  12. Kenneth Purtell says:

    Great thanks.

    What if you want to keep an empty or tag and only lose the tag?

    As in:

    Name

  13. Kenneth Purtell says:

    Great thanks.

    What if you want to keep an empty or tag and only lose the tag?

    As in:


    Name

  14. Kenneth Purtell says:

    Great thanks.

    What if you want to keep an empty or tag and only lose the tag?

    As in:

    Name
    
    
    
    
  15. Kenneth Purtell says:

    It’s ok, I figured it out:


    $this->addElement('submit', 'submit', array(
    'required' => false,
    'ignore' => true,
    'label' => 'Submit',
    'decorators' => array(
    'ViewHelper',
    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element')),
    array(array('label' => 'HtmlTag'), array('tag' => 'th', 'placement' => 'prepend')),
    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
    )));

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>