[ZF-10089] Zend_Log
[zend.git] / documentation / manual / en / module_specs / Zend_Form-QuickStart.xml
blob90457a91219cb69b00542162868e0d1aa2f1f3d4
1 <?xml version="1.0" encoding="UTF-8"?>
2 <!-- Reviewed: no -->
3 <sect1 id="zend.form.quickstart">
4     <title>Zend_Form Quick Start</title>
6     <para>
7         This quick start guide covers the basics of creating,
8         validating, and rendering forms with <classname>Zend_Form</classname>.
9     </para>
11     <sect2 id="zend.form.quickstart.create">
12         <title>Create a form object</title>
14         <para>
15             Creating a form object is very simple: simply instantiate
16             <classname>Zend_Form</classname>:
17         </para>
19         <programlisting language="php"><![CDATA[
20 $form = new Zend_Form;
21 ]]></programlisting>
23         <para>
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>
27             object.
28         </para>
30         <para>
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:
34         </para>
36         <programlisting language="php"><![CDATA[
37 $form->setAction('/resource/process')
38      ->setMethod('post');
39 ]]></programlisting>
41         <para>
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.
45         </para>
47         <para>
48             You can set additional <acronym>HTML</acronym> attributes for the
49             <emphasis>&lt;form&gt;</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:
52         </para>
54         <programlisting language="php"><![CDATA[
55 $form->setAttrib('id', 'login');
56 ]]></programlisting>
57     </sect2>
59     <sect2 id="zend.form.quickstart.elements">
60         <title>Add elements to the form</title>
62         <para>
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:
66         </para>
68         <itemizedlist>
69             <listitem><para>button</para></listitem>
71             <listitem>
72                 <para>checkbox (or many checkboxes at once with multiCheckbox)</para>
73             </listitem>
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>
84         </itemizedlist>
86         <para>
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.
91         </para>
93         <para>
94             Some examples:
95         </para>
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');
103 ]]></programlisting>
105         <para>
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
112             the fact.
113         </para>
115         <para>
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:
119         </para>
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');
129 ]]></programlisting>
131         <para>
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:
134         </para>
136         <programlisting language="php"><![CDATA[
137 // Pass a pattern
138 $username->addValidator('regex', false, array('/^[a-z]/i'));
139 ]]></programlisting>
141         <para>
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>.)
145         </para>
147         <para>
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:
151         </para>
153         <programlisting language="php"><![CDATA[
154 // Make this element required:
155 $username->setRequired(true);
156 ]]></programlisting>
158         <para>
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
161             when required.
162         </para>
164         <para>
165             Filters are registered in basically the same way as validators. For
166             illustration purposes, let's add a filter to lowercase the final
167             value:
168         </para>
170         <programlisting language="php"><![CDATA[
171 $username->addFilter('StringtoLower');
172 ]]></programlisting>
174         <para>
175             The final element setup might look like this:
176         </para>
178         <programlisting language="php"><![CDATA[
179 $username->addValidator('alnum')
180          ->addValidator('regex', false, array('/^[a-z]/'))
181          ->setRequired(true)
182          ->addFilter('StringToLower');
184 // or, more compactly:
185 $username->addValidators(array('alnum',
186         array('regex', false, '/^[a-z]/i')
187     ))
188     ->setRequired(true)
189     ->addFilters(array('StringToLower'));
190 ]]></programlisting>
192         <para>
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:
199         </para>
201         <programlisting language="php"><![CDATA[
202 $form->addElement('text', 'username', array(
203     'validators' => array(
204         'alnum',
205         array('regex', false, '/^[a-z]/i')
206     ),
207     'required' => true,
208     'filters'  => array('StringToLower'),
210 ]]></programlisting>
212         <note>
213             <para>
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.
218             </para>
219         </note>
220     </sect2>
222     <sect2 id="zend.form.quickstart.render">
223         <title>Render a form</title>
225         <para>
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.
230         </para>
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():
237 echo $form;
238 ]]></programlisting>
240         <para>
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:
246         </para>
248         <programlisting language="php"><![CDATA[
249 <?php echo $this->form ?>
250 ]]></programlisting>
252         <para>
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:
260         </para>
262         <programlisting language="php"><![CDATA[
263 $element->addDecorators(array(
264     'ViewHelper',
265     'Errors',
266     array('HtmlTag', array('tag' => 'dd')),
267     array('Label', array('tag' => 'dt')),
269 ]]></programlisting>
271         <para>
272             (Where &lt;HELPERNAME&gt; is the name of a view helper to use, and varies
273             based on the element.)
274         </para>
276         <para>
277             The above creates output like the following:
278         </para>
280         <programlisting language="html"><![CDATA[
281 <dt><label for="username" class="required">Username</dt>
282 <dd>
283     <input type="text" name="username" value="123-abc" />
284     <ul class="errors">
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>
287     </ul>
288 </dd>
289 ]]></programlisting>
291         <para>
292             (Albeit not with the same formatting.)
293         </para>
295         <para>
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
298             information.
299         </para>
301         <para>
302             The form itself simply loops through the elements, and dresses them
303             in an <acronym>HTML</acronym> <emphasis>&lt;form&gt;</emphasis>. The action and method
304             you provided when setting up the form are provided to the
305             <emphasis>&lt;form&gt;</emphasis> tag, as are any attributes you set via
306             <methodname>setAttribs()</methodname> and family.
307         </para>
309         <para>
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:
313         </para>
315         <programlisting language="php"><![CDATA[
316 $element->setOrder(10);
317 ]]></programlisting>
319         <para>
320             Or, when creating an element, by passing it as an option:
321         </para>
323         <programlisting language="php"><![CDATA[
324 $form->addElement('text', 'username', array('order' => 10));
325 ]]></programlisting>
326     </sect2>
328     <sect2 id="zend.form.quickstart.validate">
329         <title>Check if a form is valid</title>
331         <para>
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>
336             value.
337         </para>
339         <para>
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):
343         </para>
345         <programlisting language="php"><![CDATA[
346 if ($form->isValid($_POST)) {
347     // success!
348 } else {
349     // failure!
351 ]]></programlisting>
353         <para>
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:
359         </para>
361         <programlisting language="php"><![CDATA[
362 if ($form->isValidPartial($_POST)) {
363     // elements present all passed validations
364 } else {
365     // one or more elements tested failed validations
367 ]]></programlisting>
369         <para>
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
373             failure.
374         </para>
376         <para>
377             Assuming your validations have passed, you can now fetch the
378             filtered values:
379         </para>
381         <programlisting language="php"><![CDATA[
382 $values = $form->getValues();
383 ]]></programlisting>
385         <para>
386             If you need the unfiltered values at any point, use:
387         </para>
389         <programlisting language="php"><![CDATA[
390 $unfiltered = $form->getUnfilteredValues();
391 ]]></programlisting>
393         <para>
394             If you on the other hand need all the valid and filtered values of a partially valid
395             form, you can call:
396         </para>
398         <programlisting language="php"><![CDATA[
399 $values = $form->getValidValues($_POST);
400 ]]></programlisting>
401     </sect2>
403     <sect2 id="zend.form.quickstart.errorstatus">
404         <title>Get error status</title>
406         <para>
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
409             default decorators:
410         </para>
412         <programlisting language="php"><![CDATA[
413 if (!$form->isValid($_POST)) {
414     echo $form;
416     // or assign to the view object and render a view...
417     $this->view->form = $form;
418     return $this->render('form');
420 ]]></programlisting>
422         <para>
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.
430         </para>
431     </sect2>
433     <sect2 id="zend.form.quickstart.puttingtogether">
434         <title>Putting it together</title>
436         <para>
437             Let's build a simple login form. It will need elements
438             representing:
439         </para>
441         <itemizedlist>
442             <listitem><para>username</para></listitem>
443             <listitem><para>password</para></listitem>
444             <listitem><para>submit</para></listitem>
445         </itemizedlist>
447         <para>
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
453             unvalidated.
454         </para>
456         <para>
457             We'll use the power of <classname>Zend_Form</classname>'s configuration
458             options to build the form:
459         </para>
461         <programlisting language="php"><![CDATA[
462 $form = new Zend_Form();
463 $form->setAction('/user/login')
464      ->setMethod('post');
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))
471          ->setRequired(true)
472          ->addFilter('StringToLower');
474 // Create and configure password element:
475 $password = $form->createElement('password', 'password');
476 $password->addValidator('StringLength', false, array(6))
477          ->setRequired(true);
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'));
484 ]]></programlisting>
486         <para>
487             Next, we'll create a controller for handling this:
488         </para>
490         <programlisting language="php"><![CDATA[
491 class UserController extends Zend_Controller_Action
493     public function getForm()
494     {
495         // create form as above
496         return $form;
497     }
499     public function indexAction()
500     {
501         // render user/form.phtml
502         $this->view->form = $this->getForm();
503         $this->render('form');
504     }
506     public function loginAction()
507     {
508         if (!$this->getRequest()->isPost()) {
509             return $this->_forward('index');
510         }
511         $form = $this->getForm();
512         if (!$form->isValid($_POST)) {
513             // Failed validation; redisplay form
514             $this->view->form = $form;
515             return $this->render('form');
516         }
518         $values = $form->getValues();
519         // now try and authenticate....
520     }
522 ]]></programlisting>
524         <para>
525             And a view script for displaying the form:
526         </para>
528         <programlisting language="php"><![CDATA[
529 <h2>Please login:</h2>
530 <?php echo $this->form ?>
531 ]]></programlisting>
533         <para>
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.
537         </para>
538     </sect2>
540     <sect2 id="zend.form.quickstart.config">
541         <title>Using a Zend_Config Object</title>
543         <para>
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'):
553         </para>
555         <programlisting language="ini"><![CDATA[
556 [development]
557 ; general form metainformation
558 user.login.action = "/user/login"
559 user.login.method = "post"
561 ; username element
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"
572 ; password element
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
578 ; submit element
579 user.login.elements.submit.type = "submit"
580 ]]></programlisting>
582         <para>
583             You would then pass this to the form constructor:
584         </para>
586         <programlisting language="php"><![CDATA[
587 $config = new Zend_Config_Ini($configFile, 'development');
588 $form   = new Zend_Form($config->user->login);
589 ]]></programlisting>
591         <para>
592             and the entire form will be defined.
593         </para>
594     </sect2>
596     <sect2 id="zend.form.quickstart.conclusion">
597         <title>Conclusion</title>
599         <para>
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!
603         </para>
604     </sect2>
605 </sect1>
606 <!--
607 vim:se ts=4 sw=4 et: