Overview
Zend Form is a great tool for creating maintainable, reusable, encapsulated forms, unfortunately the learning curve can be steep for even the more experienced programmer. I have seen many cases where programmers will abandon Zend Form and revert back to what they know, html.
Problem:
So, lets say we have a Zend SubForm and we want to reuse the same elements in our page multiple times, for this example I am going to use Members, a Member belongs to an Account and an Account can have more than one Member.
Requirement:
Have a form that allows an end user to add multiple Members to an Account from the same form.
Desired Output: (For simplicity of this example I am using only 1 element)
<ul> <li><input name="member[1][first_name]" size="30" value=""></li> <li><input name="member[2][first_name]" size="30" value=""></li> <li><input name="member[3][first_name]" size="30" value=""></li> </ul>
Solution:
In order to accomplish this, we will make 2 forms, a SubForm class and a Form class.
SubForm Class:
class Default_Form_SubForm_AddMember extends Zend_Form_SubForm { const FIRST_NAME = "first_name"; protected $rowNumber = 1; public function init() { $decorators = array( 'ViewHelper', array('HtmlTag', array('tag' => 'li', 'class' => 'form_field')) ); /* * We want array notation, so we will need to do a belongs to here. */ $this->setElementsBelongTo("member[{$this->rowNumber}]"); $this->addElement("text", self::FIRST_NAME, array("size" => 20, "title" => "")) ->getElement(self::FIRST_NAME) ->setDecorators($decorators) ->addValidator("Alnum", false, array(true)) ->addFilter('StripTags') ->addValidator("StringLength", false, array("min" => 2, "max" => 100)); } public function setRowNumber($num) { $this->rowNumber = (int) $num; return $this; } }
Form Class:
class Default_Form_Member extends Zend_Form { const SUBMIT_BUTTON = "submit"; protected $max = 10; public function init() { $this->addMemberForms(); /* * Left out the rest of the class for simplicity */ } public function addMemberForms() { for($i=0; $i < $this->max; $i++) { $key = "member_". $i; /* * Add Subform passing in current row number as well as decorate * the subform with ul */ $subform = new Account_Form_AddMemberSubForm(array("RowNumber" => ($i+1))); $this->addSubForm($subform, $key) ->getSubForm($key) ->clearDecorators() ->addDecorator('FormElements') ->addDecorator('HtmlTag', array("tag" => "ul")); } } /* * Set the Max fields to show, this value is passed to the form constructor * new form(array('Max' => 10)); */ public function setMax($max) { $this->max = $max; return $this; } }

2 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.
Thanks a lot :O I was looking for this
Thanks for the short, sweet, simple, and easy to follow post. It was exactly what I needed. I didn’t realize you could do array notation in BelongTo.