File: Zend_Form-QuickStart.xml

package info (click to toggle)
zendframework 1.12.9%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie-kfreebsd
  • size: 133,584 kB
  • sloc: xml: 1,311,829; php: 570,173; sh: 170; makefile: 125; sql: 121
file content (608 lines) | stat: -rw-r--r-- 21,761 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<sect1 id="zend.form.quickstart">
    <title>Zend_Form Quick Start</title>

    <para>
        This quick start guide covers the basics of creating,
        validating, and rendering forms with <classname>Zend_Form</classname>.
    </para>

    <sect2 id="zend.form.quickstart.create">
        <title>Create a form object</title>

        <para>
            Creating a form object is very simple: simply instantiate
            <classname>Zend_Form</classname>:
        </para>

        <programlisting language="php"><![CDATA[
$form = new Zend_Form;
]]></programlisting>

        <para>
            For advanced use cases, you may want to create a
            <classname>Zend_Form</classname> subclass, but for simple forms, you can
            create a form programmatically using a <classname>Zend_Form</classname>
            object.
        </para>

        <para>
            If you wish to specify the form action and method (always good
            ideas), you can do so with the <methodname>setAction()</methodname> and
            <methodname>setMethod()</methodname> accessors:
        </para>

        <programlisting language="php"><![CDATA[
$form->setAction('/resource/process')
     ->setMethod('post');
]]></programlisting>

        <para>
            The above code sets the form action to the partial <acronym>URL</acronym>
            "<filename>/resource/process</filename>" and the form method to <acronym>HTTP</acronym>
            <acronym>POST</acronym>. This will be reflected during final rendering.
        </para>

        <para>
            You can set additional <acronym>HTML</acronym> attributes for the
            <emphasis>&lt;form&gt;</emphasis> tag by using the <methodname>setAttrib()</methodname>
            or <methodname>setAttribs()</methodname> methods. For instance, if you wish to set the
            id, set the "<property>id</property>" attribute:
        </para>

        <programlisting language="php"><![CDATA[
$form->setAttrib('id', 'login');
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.elements">
        <title>Add elements to the form</title>

        <para>
            A form is nothing without its elements. <classname>Zend_Form</classname>
            ships with some default elements that render <acronym>XHTML</acronym> via
            <classname>Zend_View</classname> helpers. These are as follows:
        </para>

        <itemizedlist>
            <listitem><para>button</para></listitem>

            <listitem>
                <para>checkbox (or many checkboxes at once with multiCheckbox)</para>
            </listitem>

            <listitem><para>hidden</para></listitem>
            <listitem><para>image</para></listitem>
            <listitem><para>password</para></listitem>
            <listitem><para>radio</para></listitem>
            <listitem><para>reset</para></listitem>
            <listitem><para>select (both regular and multi-select types)</para></listitem>
            <listitem><para>submit</para></listitem>
            <listitem><para>text</para></listitem>
            <listitem><para>textarea</para></listitem>
        </itemizedlist>

        <para>
            You have two options for adding elements to a form: you can
            instantiate concrete elements and pass in these objects, or you can
            pass in simply the element type and have <classname>Zend_Form</classname>
            instantiate an object of the correct type for you.
        </para>

        <para>
            Some examples:
        </para>

        <programlisting language="php"><![CDATA[
// Instantiating an element and passing to the form object:
$form->addElement(new Zend_Form_Element_Text('username'));

// Passing a form element type to the form object:
$form->addElement('text', 'username');
]]></programlisting>

        <para>
            By default, these do not have any validators or filters. This means
            you will need to configure your elements with at least validators,
            and potentially filters. You can either do this (a) before you pass
            the element to the form, (b) via configuration options passed in
            when creating an element via <classname>Zend_Form</classname>, or (c) by
            pulling the element from the form object and configuring it after
            the fact.
        </para>

        <para>
            Let's first look at creating validators for a concrete element
            instance. You can either pass in <classname>Zend_Validate_*</classname>
            objects, or the name of a validator to utilize:
        </para>

        <programlisting language="php"><![CDATA[
$username = new Zend_Form_Element_Text('username');

// Passing a Zend_Validate_* object:
$username->addValidator(new Zend_Validate_Alnum());

// Passing a validator name:
$username->addValidator('alnum');
]]></programlisting>

        <para>
            When using this second option, you can pass constructor arguments in an array as the
            third parameter if the validator can accept tem:
        </para>

        <programlisting language="php"><![CDATA[
// Pass a pattern
$username->addValidator('regex', false, array('/^[a-z]/i'));
]]></programlisting>

        <para>
            (The second parameter is used to indicate whether or not failure of
            this validator should prevent later validators from running; by
            default, this is <constant>FALSE</constant>.)
        </para>

        <para>
            You may also wish to specify an element as required. This can be
            done using an accessor or passing an option when creating
            the element. In the former case:
        </para>

        <programlisting language="php"><![CDATA[
// Make this element required:
$username->setRequired(true);
]]></programlisting>

        <para>
            When an element is required, a 'NotEmpty' validator is added to the
            top of the validator chain, ensuring that the element has a value
            when required.
        </para>

        <para>
            Filters are registered in basically the same way as validators. For
            illustration purposes, let's add a filter to lowercase the final
            value:
        </para>

        <programlisting language="php"><![CDATA[
$username->addFilter('StringtoLower');
]]></programlisting>

        <para>
            The final element setup might look like this:
        </para>

        <programlisting language="php"><![CDATA[
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]/'))
         ->setRequired(true)
         ->addFilter('StringToLower');

// or, more compactly:
$username->addValidators(array('alnum',
        array('regex', false, '/^[a-z]/i')
    ))
    ->setRequired(true)
    ->addFilters(array('StringToLower'));
]]></programlisting>

        <para>
            Simple as this is, repeating it this for every element in a form
            can be a bit tedious. Let's try option (b) from above. When we
            create a new element using <methodname>Zend_Form::addElement()</methodname> as
            a factory, we can optionally pass in configuration options. These
            can include validators and filters. To do all of the
            above implicitly, try the following:
        </para>

        <programlisting language="php"><![CDATA[
$form->addElement('text', 'username', array(
    'validators' => array(
        'alnum',
        array('regex', false, '/^[a-z]/i')
    ),
    'required' => true,
    'filters'  => array('StringToLower'),
));
]]></programlisting>

        <note>
            <para>
                If you find you are setting up elements using the same options in
                many locations, you may want to consider creating your own
                <classname>Zend_Form_Element</classname> subclass and utilizing that class
                instead; this will save you typing in the long-run.
            </para>
        </note>
    </sect2>

    <sect2 id="zend.form.quickstart.render">
        <title>Render a form</title>

        <para>
            Rendering a form is simple. Most elements use a
            <classname>Zend_View</classname> helper to render themselves, and thus need a
            view object in order to render. Other than that, you have two
            options: use the form's render() method, or simply echo it.
        </para>

        <programlisting language="php"><![CDATA[
// Explicitly calling render(), and passing an optional view object:
echo $form->render($view);

// Assuming a view object has been previously set via setView():
echo $form;
]]></programlisting>

        <para>
            By default, <classname>Zend_Form</classname> and
            <classname>Zend_Form_Element</classname> will attempt to use the view object
            initialized in the <classname>ViewRenderer</classname>, which means you won't
            need to set the view manually when using the Zend Framework <acronym>MVC</acronym>.
            To render a form in a view, you simply have to do the following:
        </para>

        <programlisting language="php"><![CDATA[
<?php echo $this->form ?>
]]></programlisting>

        <para>
            Under the hood, <classname>Zend_Form</classname> uses "decorators" to perform
            rendering. These decorators can replace content, append content, or
            prepend content, and can fully introspect the element passed
            to them. As a result, you can combine multiple decorators to
            achieve custom effects. By default, <classname>Zend_Form_Element</classname>
            actually combines four decorators to achieve its output; setup
            looks something like this:
        </para>

        <programlisting language="php"><![CDATA[
$element->addDecorators(array(
    'ViewHelper',
    'Errors',
    array('HtmlTag', array('tag' => 'dd')),
    array('Label', array('tag' => 'dt')),
));
]]></programlisting>

        <para>
            (Where &lt;HELPERNAME&gt; is the name of a view helper to use, and varies
            based on the element.)
        </para>

        <para>
            The above creates output like the following:
        </para>

        <programlisting language="html"><![CDATA[
<dt><label for="username" class="required">Username</dt>
<dd>
    <input type="text" name="username" value="123-abc" />
    <ul class="errors">
        <li>'123-abc' has not only alphabetic and digit characters</li>
        <li>'123-abc' does not match against pattern '/^[a-z]/i'</li>
    </ul>
</dd>
]]></programlisting>

        <para>
            (Albeit not with the same formatting.)
        </para>

        <para>
            You can change the decorators used by an element if you wish to
            have different output; see the section on decorators for more
            information.
        </para>

        <para>
            The form itself simply loops through the elements, and dresses them
            in an <acronym>HTML</acronym> <emphasis>&lt;form&gt;</emphasis>. The action and method
            you provided when setting up the form are provided to the
            <emphasis>&lt;form&gt;</emphasis> tag, as are any attributes you set via
            <methodname>setAttribs()</methodname> and family.
        </para>

        <para>
            Elements are looped either in the order in which they were
            registered, or, if your element contains an order attribute, that
            order will be used. You can set an element's order using:
        </para>

        <programlisting language="php"><![CDATA[
$element->setOrder(10);
]]></programlisting>

        <para>
            Or, when creating an element, by passing it as an option:
        </para>

        <programlisting language="php"><![CDATA[
$form->addElement('text', 'username', array('order' => 10));
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.validate">
        <title>Check if a form is valid</title>

        <para>
            After a form is submitted, you will need to check and see if it
            passes validations. Each element is checked against the data
            provided; if a key matching the element name is not present, and
            the item is marked as required, validations are run with a <constant>NULL</constant>
            value.
        </para>

        <para>
            Where does the data come from? You can use <varname>$_POST</varname> or
            <varname>$_GET</varname>, or any other data source you might have at hand
            (web service requests, for instance):
        </para>

        <programlisting language="php"><![CDATA[
if ($form->isValid($_POST)) {
    // success!
} else {
    // failure!
}
]]></programlisting>

        <para>
            With <acronym>AJAX</acronym> requests, you can sometimes get away with validating
            a single element, or groups of elements.
            <methodname>isValidPartial()</methodname> will validate a partial form. Unlike
            <methodname>isValid()</methodname>, however, if a particular key is not
            present, it will not run validations for that particular element:
        </para>

        <programlisting language="php"><![CDATA[
if ($form->isValidPartial($_POST)) {
    // elements present all passed validations
} else {
    // one or more elements tested failed validations
}
]]></programlisting>

        <para>
            An additional method, <methodname>processAjax()</methodname>, can be used
            for validating partial forms. Unlike <methodname>isValidPartial()</methodname>,
            it returns a <acronym>JSON</acronym>-formatted string containing error messages on
            failure.
        </para>

        <para>
            Assuming your validations have passed, you can now fetch the
            filtered values:
        </para>

        <programlisting language="php"><![CDATA[
$values = $form->getValues();
]]></programlisting>

        <para>
            If you need the unfiltered values at any point, use:
        </para>

        <programlisting language="php"><![CDATA[
$unfiltered = $form->getUnfilteredValues();
]]></programlisting>

        <para>
            If you on the other hand need all the valid and filtered values of a partially valid
            form, you can call:
        </para>

        <programlisting language="php"><![CDATA[
$values = $form->getValidValues($_POST);
]]></programlisting>
    </sect2>

    <sect2 id="zend.form.quickstart.errorstatus">
        <title>Get error status</title>

        <para>
            Did your form have failed validations on submission? In most cases, you can simply
            render the form again, and errors will be displayed when using the
            default decorators:
        </para>

        <programlisting language="php"><![CDATA[
if (!$form->isValid($_POST)) {
    echo $form;

    // or assign to the view object and render a view...
    $this->view->form = $form;
    return $this->render('form');
}
]]></programlisting>

        <para>
            If you want to inspect the errors, you have two methods.
            <methodname>getErrors()</methodname> returns an associative array of element
            names / codes (where codes is an array of error codes).
            <methodname>getMessages()</methodname> returns an associative array of element
            names / messages (where messages is an associative array of error
            code / error message pairs). If a given element does not have any
            errors, it will not be included in the array.
        </para>
    </sect2>

    <sect2 id="zend.form.quickstart.puttingtogether">
        <title>Putting it together</title>

        <para>
            Let's build a simple login form. It will need elements
            representing:
        </para>

        <itemizedlist>
            <listitem><para>username</para></listitem>
            <listitem><para>password</para></listitem>
            <listitem><para>submit</para></listitem>
        </itemizedlist>

        <para>
            For our purposes, let's assume that a valid username should be
            alphanumeric characters only, start with a letter, have a minimum
            length of 6, and maximum length of 20; they will be normalized to
            lowercase. Passwords must be a minimum of 6 characters. We'll
            simply toss the submit value when done, so it can remain
            unvalidated.
        </para>

        <para>
            We'll use the power of <classname>Zend_Form</classname>'s configuration
            options to build the form:
        </para>

        <programlisting language="php"><![CDATA[
$form = new Zend_Form();
$form->setAction('/user/login')
     ->setMethod('post');

// Create and configure username element:
$username = $form->createElement('text', 'username');
$username->addValidator('alnum')
         ->addValidator('regex', false, array('/^[a-z]+/'))
         ->addValidator('stringLength', false, array(6, 20))
         ->setRequired(true)
         ->addFilter('StringToLower');

// Create and configure password element:
$password = $form->createElement('password', 'password');
$password->addValidator('StringLength', false, array(6))
         ->setRequired(true);

// Add elements to form:
$form->addElement($username)
     ->addElement($password)
     // use addElement() as a factory to create 'Login' button:
     ->addElement('submit', 'login', array('label' => 'Login'));
]]></programlisting>

        <para>
            Next, we'll create a controller for handling this:
        </para>

        <programlisting language="php"><![CDATA[
class UserController extends Zend_Controller_Action
{
    public function getForm()
    {
        // create form as above
        return $form;
    }

    public function indexAction()
    {
        // render user/form.phtml
        $this->view->form = $this->getForm();
        $this->render('form');
    }

    public function loginAction()
    {
        if (!$this->getRequest()->isPost()) {
            return $this->_forward('index');
        }
        $form = $this->getForm();
        if (!$form->isValid($_POST)) {
            // Failed validation; redisplay form
            $this->view->form = $form;
            return $this->render('form');
        }

        $values = $form->getValues();
        // now try and authenticate....
    }
}
]]></programlisting>

        <para>
            And a view script for displaying the form:
        </para>

        <programlisting language="php"><![CDATA[
<h2>Please login:</h2>
<?php echo $this->form ?>
]]></programlisting>

        <para>
            As you'll note from the controller code, there's more work to do:
            while the submission may be valid, you may still need to do some authentication
            using <classname>Zend_Auth</classname> or another authorization mechanism.
        </para>
    </sect2>

    <sect2 id="zend.form.quickstart.config">
        <title>Using a Zend_Config Object</title>

        <para>
            All <classname>Zend_Form</classname> classes are configurable using
            <classname>Zend_Config</classname>; you can either pass a
            <classname>Zend_Config</classname> object to the constructor or pass it in
            with <methodname>setConfig()</methodname>. Let's look at how we might create the
            above form using an <acronym>INI</acronym> file. First, let's follow the
            recommendations, and place our configurations into sections
            reflecting the release location, and focus on the 'development'
            section. Next, we'll setup a section for the given controller
            ('user'), and a key for the form ('login'):
        </para>

        <programlisting language="ini"><![CDATA[
[development]
; general form metainformation
user.login.action = "/user/login"
user.login.method = "post"

; username element
user.login.elements.username.type = "text"
user.login.elements.username.options.validators.alnum.validator = "alnum"
user.login.elements.username.options.validators.regex.validator = "regex"
user.login.elements.username.options.validators.regex.options.pattern = "/^[a-z]/i"
user.login.elements.username.options.validators.strlen.validator = "StringLength"
user.login.elements.username.options.validators.strlen.options.min = "6"
user.login.elements.username.options.validators.strlen.options.max = "20"
user.login.elements.username.options.required = true
user.login.elements.username.options.filters.lower.filter = "StringToLower"

; password element
user.login.elements.password.type = "password"
user.login.elements.password.options.validators.strlen.validator = "StringLength"
user.login.elements.password.options.validators.strlen.options.min = "6"
user.login.elements.password.options.required = true

; submit element
user.login.elements.submit.type = "submit"
]]></programlisting>

        <para>
            You would then pass this to the form constructor:
        </para>

        <programlisting language="php"><![CDATA[
$config = new Zend_Config_Ini($configFile, 'development');
$form   = new Zend_Form($config->user->login);
]]></programlisting>

        <para>
            and the entire form will be defined.
        </para>
    </sect2>

    <sect2 id="zend.form.quickstart.conclusion">
        <title>Conclusion</title>

        <para>
            Hopefully with this little tutorial, you should now be well on your
            way to unlocking the power and flexibility of
            <classname>Zend_Form</classname>. Read on for more in-depth information!
        </para>
    </sect2>
</sect1>
<!--
vim:se ts=4 sw=4 et:
-->