1 <?xml version="1.0" encoding="UTF-8"?>
3 <sect1 id="zend.form.quickstart">
4 <title>Zend_Form Quick Start</title>
7 This quick start guide covers the basics of creating,
8 validating, and rendering forms with <classname>Zend_Form</classname>.
11 <sect2 id="zend.form.quickstart.create">
12 <title>Create a form object</title>
15 Creating a form object is very simple: simply instantiate
16 <classname>Zend_Form</classname>:
19 <programlisting language="php"><![CDATA[
20 $form = new Zend_Form;
24 For advanced use cases, you may want to create a
25 <classname>Zend_Form</classname> subclass, but for simple forms, you can
26 create a form programmatically using a <classname>Zend_Form</classname>
31 If you wish to specify the form action and method (always good
32 ideas), you can do so with the <methodname>setAction()</methodname> and
33 <methodname>setMethod()</methodname> accessors:
36 <programlisting language="php"><![CDATA[
37 $form->setAction('/resource/process')
42 The above code sets the form action to the partial <acronym>URL</acronym>
43 "<filename>/resource/process</filename>" and the form method to <acronym>HTTP</acronym>
44 <acronym>POST</acronym>. This will be reflected during final rendering.
48 You can set additional <acronym>HTML</acronym> attributes for the
49 <emphasis><form></emphasis> tag by using the <methodname>setAttrib()</methodname>
50 or <methodname>setAttribs()</methodname> methods. For instance, if you wish to set the
51 id, set the "<property>id</property>" attribute:
54 <programlisting language="php"><![CDATA[
55 $form->setAttrib('id', 'login');
59 <sect2 id="zend.form.quickstart.elements">
60 <title>Add elements to the form</title>
63 A form is nothing without its elements. <classname>Zend_Form</classname>
64 ships with some default elements that render <acronym>XHTML</acronym> via
65 <classname>Zend_View</classname> helpers. These are as follows:
69 <listitem><para>button</para></listitem>
72 <para>checkbox (or many checkboxes at once with multiCheckbox)</para>
75 <listitem><para>hidden</para></listitem>
76 <listitem><para>image</para></listitem>
77 <listitem><para>password</para></listitem>
78 <listitem><para>radio</para></listitem>
79 <listitem><para>reset</para></listitem>
80 <listitem><para>select (both regular and multi-select types)</para></listitem>
81 <listitem><para>submit</para></listitem>
82 <listitem><para>text</para></listitem>
83 <listitem><para>textarea</para></listitem>
87 You have two options for adding elements to a form: you can
88 instantiate concrete elements and pass in these objects, or you can
89 pass in simply the element type and have <classname>Zend_Form</classname>
90 instantiate an object of the correct type for you.
97 <programlisting language="php"><![CDATA[
98 // Instantiating an element and passing to the form object:
99 $form->addElement(new Zend_Form_Element_Text('username'));
101 // Passing a form element type to the form object:
102 $form->addElement('text', 'username');
106 By default, these do not have any validators or filters. This means
107 you will need to configure your elements with at least validators,
108 and potentially filters. You can either do this (a) before you pass
109 the element to the form, (b) via configuration options passed in
110 when creating an element via <classname>Zend_Form</classname>, or (c) by
111 pulling the element from the form object and configuring it after
116 Let's first look at creating validators for a concrete element
117 instance. You can either pass in <classname>Zend_Validate_*</classname>
118 objects, or the name of a validator to utilize:
121 <programlisting language="php"><![CDATA[
122 $username = new Zend_Form_Element_Text('username');
124 // Passing a Zend_Validate_* object:
125 $username->addValidator(new Zend_Validate_Alnum());
127 // Passing a validator name:
128 $username->addValidator('alnum');
132 When using this second option, you can pass constructor arguments in an array as the
133 third parameter if the validator can accept tem:
136 <programlisting language="php"><![CDATA[
138 $username->addValidator('regex', false, array('/^[a-z]/i'));
142 (The second parameter is used to indicate whether or not failure of
143 this validator should prevent later validators from running; by
144 default, this is <constant>FALSE</constant>.)
148 You may also wish to specify an element as required. This can be
149 done using an accessor or passing an option when creating
150 the element. In the former case:
153 <programlisting language="php"><![CDATA[
154 // Make this element required:
155 $username->setRequired(true);
159 When an element is required, a 'NotEmpty' validator is added to the
160 top of the validator chain, ensuring that the element has a value
165 Filters are registered in basically the same way as validators. For
166 illustration purposes, let's add a filter to lowercase the final
170 <programlisting language="php"><![CDATA[
171 $username->addFilter('StringtoLower');
175 The final element setup might look like this:
178 <programlisting language="php"><![CDATA[
179 $username->addValidator('alnum')
180 ->addValidator('regex', false, array('/^[a-z]/'))
182 ->addFilter('StringToLower');
184 // or, more compactly:
185 $username->addValidators(array('alnum',
186 array('regex', false, '/^[a-z]/i')
189 ->addFilters(array('StringToLower'));
193 Simple as this is, repeating it this for every element in a form
194 can be a bit tedious. Let's try option (b) from above. When we
195 create a new element using <methodname>Zend_Form::addElement()</methodname> as
196 a factory, we can optionally pass in configuration options. These
197 can include validators and filters. To do all of the
198 above implicitly, try the following:
201 <programlisting language="php"><![CDATA[
202 $form->addElement('text', 'username', array(
203 'validators' => array(
205 array('regex', false, '/^[a-z]/i')
208 'filters' => array('StringToLower'),
214 If you find you are setting up elements using the same options in
215 many locations, you may want to consider creating your own
216 <classname>Zend_Form_Element</classname> subclass and utilizing that class
217 instead; this will save you typing in the long-run.
222 <sect2 id="zend.form.quickstart.render">
223 <title>Render a form</title>
226 Rendering a form is simple. Most elements use a
227 <classname>Zend_View</classname> helper to render themselves, and thus need a
228 view object in order to render. Other than that, you have two
229 options: use the form's render() method, or simply echo it.
232 <programlisting language="php"><![CDATA[
233 // Explicitly calling render(), and passing an optional view object:
234 echo $form->render($view);
236 // Assuming a view object has been previously set via setView():
241 By default, <classname>Zend_Form</classname> and
242 <classname>Zend_Form_Element</classname> will attempt to use the view object
243 initialized in the <classname>ViewRenderer</classname>, which means you won't
244 need to set the view manually when using the Zend Framework <acronym>MVC</acronym>.
245 To render a form in a view, you simply have to do the following:
248 <programlisting language="php"><![CDATA[
249 <?php echo $this->form ?>
253 Under the hood, <classname>Zend_Form</classname> uses "decorators" to perform
254 rendering. These decorators can replace content, append content, or
255 prepend content, and can fully introspect the element passed
256 to them. As a result, you can combine multiple decorators to
257 achieve custom effects. By default, <classname>Zend_Form_Element</classname>
258 actually combines four decorators to achieve its output; setup
259 looks something like this:
262 <programlisting language="php"><![CDATA[
263 $element->addDecorators(array(
266 array('HtmlTag', array('tag' => 'dd')),
267 array('Label', array('tag' => 'dt')),
272 (Where <HELPERNAME> is the name of a view helper to use, and varies
273 based on the element.)
277 The above creates output like the following:
280 <programlisting language="html"><![CDATA[
281 <dt><label for="username" class="required">Username</dt>
283 <input type="text" name="username" value="123-abc" />
285 <li>'123-abc' has not only alphabetic and digit characters</li>
286 <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
292 (Albeit not with the same formatting.)
296 You can change the decorators used by an element if you wish to
297 have different output; see the section on decorators for more
302 The form itself simply loops through the elements, and dresses them
303 in an <acronym>HTML</acronym> <emphasis><form></emphasis>. The action and method
304 you provided when setting up the form are provided to the
305 <emphasis><form></emphasis> tag, as are any attributes you set via
306 <methodname>setAttribs()</methodname> and family.
310 Elements are looped either in the order in which they were
311 registered, or, if your element contains an order attribute, that
312 order will be used. You can set an element's order using:
315 <programlisting language="php"><![CDATA[
316 $element->setOrder(10);
320 Or, when creating an element, by passing it as an option:
323 <programlisting language="php"><![CDATA[
324 $form->addElement('text', 'username', array('order' => 10));
328 <sect2 id="zend.form.quickstart.validate">
329 <title>Check if a form is valid</title>
332 After a form is submitted, you will need to check and see if it
333 passes validations. Each element is checked against the data
334 provided; if a key matching the element name is not present, and
335 the item is marked as required, validations are run with a <constant>NULL</constant>
340 Where does the data come from? You can use <varname>$_POST</varname> or
341 <varname>$_GET</varname>, or any other data source you might have at hand
342 (web service requests, for instance):
345 <programlisting language="php"><![CDATA[
346 if ($form->isValid($_POST)) {
354 With <acronym>AJAX</acronym> requests, you can sometimes get away with validating
355 a single element, or groups of elements.
356 <methodname>isValidPartial()</methodname> will validate a partial form. Unlike
357 <methodname>isValid()</methodname>, however, if a particular key is not
358 present, it will not run validations for that particular element:
361 <programlisting language="php"><![CDATA[
362 if ($form->isValidPartial($_POST)) {
363 // elements present all passed validations
365 // one or more elements tested failed validations
370 An additional method, <methodname>processAjax()</methodname>, can be used
371 for validating partial forms. Unlike <methodname>isValidPartial()</methodname>,
372 it returns a <acronym>JSON</acronym>-formatted string containing error messages on
377 Assuming your validations have passed, you can now fetch the
381 <programlisting language="php"><![CDATA[
382 $values = $form->getValues();
386 If you need the unfiltered values at any point, use:
389 <programlisting language="php"><![CDATA[
390 $unfiltered = $form->getUnfilteredValues();
394 If you on the other hand need all the valid and filtered values of a partially valid
398 <programlisting language="php"><![CDATA[
399 $values = $form->getValidValues($_POST);
403 <sect2 id="zend.form.quickstart.errorstatus">
404 <title>Get error status</title>
407 Did your form have failed validations on submission? In most cases, you can simply
408 render the form again, and errors will be displayed when using the
412 <programlisting language="php"><![CDATA[
413 if (!$form->isValid($_POST)) {
416 // or assign to the view object and render a view...
417 $this->view->form = $form;
418 return $this->render('form');
423 If you want to inspect the errors, you have two methods.
424 <methodname>getErrors()</methodname> returns an associative array of element
425 names / codes (where codes is an array of error codes).
426 <methodname>getMessages()</methodname> returns an associative array of element
427 names / messages (where messages is an associative array of error
428 code / error message pairs). If a given element does not have any
429 errors, it will not be included in the array.
433 <sect2 id="zend.form.quickstart.puttingtogether">
434 <title>Putting it together</title>
437 Let's build a simple login form. It will need elements
442 <listitem><para>username</para></listitem>
443 <listitem><para>password</para></listitem>
444 <listitem><para>submit</para></listitem>
448 For our purposes, let's assume that a valid username should be
449 alphanumeric characters only, start with a letter, have a minimum
450 length of 6, and maximum length of 20; they will be normalized to
451 lowercase. Passwords must be a minimum of 6 characters. We'll
452 simply toss the submit value when done, so it can remain
457 We'll use the power of <classname>Zend_Form</classname>'s configuration
458 options to build the form:
461 <programlisting language="php"><![CDATA[
462 $form = new Zend_Form();
463 $form->setAction('/user/login')
466 // Create and configure username element:
467 $username = $form->createElement('text', 'username');
468 $username->addValidator('alnum')
469 ->addValidator('regex', false, array('/^[a-z]+/'))
470 ->addValidator('stringLength', false, array(6, 20))
472 ->addFilter('StringToLower');
474 // Create and configure password element:
475 $password = $form->createElement('password', 'password');
476 $password->addValidator('StringLength', false, array(6))
479 // Add elements to form:
480 $form->addElement($username)
481 ->addElement($password)
482 // use addElement() as a factory to create 'Login' button:
483 ->addElement('submit', 'login', array('label' => 'Login'));
487 Next, we'll create a controller for handling this:
490 <programlisting language="php"><![CDATA[
491 class UserController extends Zend_Controller_Action
493 public function getForm()
495 // create form as above
499 public function indexAction()
501 // render user/form.phtml
502 $this->view->form = $this->getForm();
503 $this->render('form');
506 public function loginAction()
508 if (!$this->getRequest()->isPost()) {
509 return $this->_forward('index');
511 $form = $this->getForm();
512 if (!$form->isValid($_POST)) {
513 // Failed validation; redisplay form
514 $this->view->form = $form;
515 return $this->render('form');
518 $values = $form->getValues();
519 // now try and authenticate....
525 And a view script for displaying the form:
528 <programlisting language="php"><![CDATA[
529 <h2>Please login:</h2>
530 <?php echo $this->form ?>
534 As you'll note from the controller code, there's more work to do:
535 while the submission may be valid, you may still need to do some authentication
536 using <classname>Zend_Auth</classname> or another authorization mechanism.
540 <sect2 id="zend.form.quickstart.config">
541 <title>Using a Zend_Config Object</title>
544 All <classname>Zend_Form</classname> classes are configurable using
545 <classname>Zend_Config</classname>; you can either pass a
546 <classname>Zend_Config</classname> object to the constructor or pass it in
547 with <methodname>setConfig()</methodname>. Let's look at how we might create the
548 above form using an <acronym>INI</acronym> file. First, let's follow the
549 recommendations, and place our configurations into sections
550 reflecting the release location, and focus on the 'development'
551 section. Next, we'll setup a section for the given controller
552 ('user'), and a key for the form ('login'):
555 <programlisting language="ini"><![CDATA[
557 ; general form metainformation
558 user.login.action = "/user/login"
559 user.login.method = "post"
562 user.login.elements.username.type = "text"
563 user.login.elements.username.options.validators.alnum.validator = "alnum"
564 user.login.elements.username.options.validators.regex.validator = "regex"
565 user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
566 user.login.elements.username.options.validators.strlen.validator = "StringLength"
567 user.login.elements.username.options.validators.strlen.options.min = "6"
568 user.login.elements.username.options.validators.strlen.options.max = "20"
569 user.login.elements.username.options.required = true
570 user.login.elements.username.options.filters.lower.filter = "StringToLower"
573 user.login.elements.password.type = "password"
574 user.login.elements.password.options.validators.strlen.validator = "StringLength"
575 user.login.elements.password.options.validators.strlen.options.min = "6"
576 user.login.elements.password.options.required = true
579 user.login.elements.submit.type = "submit"
583 You would then pass this to the form constructor:
586 <programlisting language="php"><![CDATA[
587 $config = new Zend_Config_Ini($configFile, 'development');
588 $form = new Zend_Form($config->user->login);
592 and the entire form will be defined.
596 <sect2 id="zend.form.quickstart.conclusion">
597 <title>Conclusion</title>
600 Hopefully with this little tutorial, you should now be well on your
601 way to unlocking the power and flexibility of
602 <classname>Zend_Form</classname>. Read on for more in-depth information!