50
Zend Framework 4. Forms Tricode Professional Services www.tricode.nl Date: 27-02-2009 Author: Marcel Blok

Zend framework 04 - forms

  • Upload
    tricode

  • View
    639

  • Download
    0

Embed Size (px)

DESCRIPTION

Zend_Form simplifies form creation and handling in your web application. It accomplishes the following goals: - Input filtering - Input validation - Element ordering - Element and Form rendering - Element and Form grouping - Element and Form-level configuration

Citation preview

Page 1: Zend framework 04 - forms

Zend Framework

4. Forms

Tricode Professional Serviceswww.tricode.nl

Date: 27-02-2009Author: Marcel Blok

Page 2: Zend framework 04 - forms

2

Zend_Form

Zend_Form simplifies form creation and handling inyour web application. It accomplishes the followinggoals:

• Input filtering• Input validation• Element ordering• Element and Form rendering• Element and Form grouping• Element and Form-level configuration

Page 3: Zend framework 04 - forms

3

Basic Form

A basic form can be as easily created as this:

In the Controller:

$this->view->form = new Zend_Form;$this->view->form ->setAction('/resource/process') ->setMethod('post') ->setAttrib('id', 'login');$this->render('form');

In the View:

<?= $this->form ?>

Page 4: Zend framework 04 - forms

4

Form elements

• button• checkbox (or many checkboxes at once with

multiCheckbox)• hidden• image• password• radio• reset• select (both regular and multi-select types)• submit• text• textarea

Page 5: Zend framework 04 - forms

5

Form elements responsibilty

Zend_Form_Element encapsulates single formelements, with the following areas of responsibility:

• Validation (Validators)• Capturing of validation error codes and

messages• Filtering (Filters)• Rendering (Decorators)• Metadata and attributes

Page 6: Zend framework 04 - forms

6

Adding Form elements

To add an element to a Form:

// Instantiating an element and passing to the form object:

$form->addElement(new Zend_Form_Element_Text('username'));

or:

// Passing a form element type to the form object:

$form->addElement('text', 'username');

Page 7: Zend framework 04 - forms

7

Form element metadata

• name• label• order• value• description

• requiredWhether the element must be used for form validation or not

• allowEmptyWhether to validate optional elements when empty or not

• autoInsertNotEmptyValidatorWhether to automatically insert the NotEmpty Validator or not

Page 8: Zend framework 04 - forms

8

Form element attributes

Form elements may require additional metadata.For XHTML form elements, for instance, you maywant to specify attributes such as the class or id.

$element->setAttrib($name, $value);

Zend_Form_Element uses overloading (using __Get

and __Set) for easy access to the Attributes:

$element->$name = $value

Page 9: Zend framework 04 - forms

9

Form element plugins

Plugins are used for

• Decorators• Validators• Filters

Page 10: Zend framework 04 - forms

10

Decorators

Decorators are used to replace, append orprepend the markup of an element

For example Zend_Form_Decorator_Label will add a

label to the element:

<input type="text" name="foo" id="foo" value="123" />

becomes:

<dt><label for="foo" class="optional">Foo</label></dt><input type="text" name="foo" id="foo" value="123" />

Page 11: Zend framework 04 - forms

11

Decorators

• Any number of decorators may be added to an element

• Decorators are called in the order they are registered to the element

• Options may be provided to the Decorator

Page 12: Zend framework 04 - forms

12

Default Decorators

• ViewHelperSpecifies a view helper to render the initial form element. By default this is the formText view helper.

• ErrorsAppends error messages to the element when errors are present.

• HtmlTagWraps the element in a <dd> tag.

• LabelPrepends a label to the element, and wraps the label in a <dt> tag.

Page 13: Zend framework 04 - forms

13

Default Decorators

• Default decorators are automatically loaded!• This behavior may be disabled.

• Manually it can be done like this:

$form->addDecorators(array(

array('ViewHelper'),

array('Errors'),

array('HtmlTag', array('tag' => 'dd')),

array('Label', array('tag' => 'dt')),

));

Page 14: Zend framework 04 - forms

14

Default Decorators

<input type="text" name="foo" id="foo" value="123" />

Becomes

<dt><label for="foo" class="optional">Foo</label></dt>

<dd>

<input type="text" name="foo" id="foo" value="123" />

<ul class="errors">

<li>Error message of a Validator</li>

</ul>

</dd>

Page 15: Zend framework 04 - forms

15

Custom Decorators

Custom Decorators can be created byimplementing Zend_Decorator_Interface

interface Zend_Decorator_Interface{

public function __construct($options = null);public function setElement($element);public function getElement();public function setOptions(array $options);public function setConfig(Zend_Config $config);public function setOption($key, $value);public function getOption($key);public function getOptions();public function removeOption($key);public function clearOptions();public function render($content);

}

Page 16: Zend framework 04 - forms

16

Custom Decorators

• Since the most often the handling of the Form element and the Options will be the same, you can also extend your custom Decorator from the Zend_Decorator_Abstract class.

• You only need to implement the render() method yourself.

Page 17: Zend framework 04 - forms

17

Custom Decorator example

class My_Decorator_Descrip extends Zend_Form_Decorator_Abstract

{

public function render($content)

{

$addition = ‘<div class=“description”>’;

$addition .= $this->getElement()->getDescription();

$addition .= ‘</div>’;

switch ($placement) {

case (self::PREPEND):

return $addition. $separator . $content;

case (self::APPEND):

default:

return $addition. $separator . $output;

}

}

}

Page 18: Zend framework 04 - forms

18

Zend_Loader_PluginLoader

Example:

class My_Decorator_Label extends Zend_Form_Decorator_Abstract{

public function render($content){

// Code to render a label before $content…

return $content;}

}

Should overwrite Zend_Form_Decorator_Label

Page 19: Zend framework 04 - forms

19

Zend_Loader_PluginLoader

Then you can tell the element to look for that plugin:

$element->addPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

Or the form:

$form->addElementPrefixPath('My_Decorator', 'My/Decorator/', 'decorator');

Page 20: Zend framework 04 - forms

20

Filters

Often you need to normalize or sanitize the userinput before using this data. For example:

• Strip HTML tags• Trim whitespace• Set to upper- or lowercase

For these actions Zend_Filter may be used.

Page 21: Zend framework 04 - forms

21

Filters

• Multiple Filters can be added to a Form element

• Like Decorators, the Filters will be triggered in order that they are added to the Form element

• Filtering is triggered during Validation

• Filtering is triggered through the getValue() method of the Form element

Page 22: Zend framework 04 - forms

22

Adding Filters

Adding Filters is much like adding Decorators:

// Concrete filter instance:

$element->addFilter(new Zend_Filter_Alnum());

// Fully qualified class name:

$element->addFilter('Zend_Filter_Alnum');

// Short filter name:

$element->addFilter('Alnum');

$element->addFilter('alnum');

Page 23: Zend framework 04 - forms

23

Standard available Filters

• Alnum• Alpha• BaseName• Digits• Dir• HtmlEntities• Int• StripNewlines• RealPath• StringToLower• StringToUpper• StringTrim• StripTags

• CamelCaseToDash• CamelCaseToSeparator• CamelCaseToUnderscore• DashToCamelCase• DashToSeparator• DashToUnderscore• SeparatorToCamelCase• SeparatorToDash• SeparatorToSeparator• UnderscoreToCamelCase• UnderscoreToDash• UnderscoreToSeparator

Page 24: Zend framework 04 - forms

24

Custom Filters

• Custom Filters can be created by implementing the Zend_Filter_Interface

interface Zend_Filter_Interface

{

/**

* Returns the result of filtering $value

*

* @param mixed $value

* @throws Zend_Filter_Exception If filtering is impossible

* @return mixed

*/

public function filter($value);

}

Page 25: Zend framework 04 - forms

25

Custom Filter example

class MyFilter implements Zend_Filter_Interface

{

public function filter($value)

{

// perform some transformation upon $value

// to arrive on $valueFiltered

return $valueFiltered;

}

}

Page 26: Zend framework 04 - forms

26

Validators

Besides marking up (“decorating”) your Forelement and transforming (“filtering”) the

captureddata, you usually also want to validate the dataprovided. For example:

• Is the input numeric?• Is the input no longer than 8 characters?• Is the input at least 4 characters long?

Page 27: Zend framework 04 - forms

27

Validators

• Multiple Validators can be added to a Form element

• Like Filters and Decorators, Validators will be triggered in order that they are added to the Form element

• A Validator may prevent the next Validators of a form Element of validating

• A single Validator may throw various error messages

Page 28: Zend framework 04 - forms

28

Adding Validators

Adding Validators is much like adding Decorators or

Filters:

// Concrete validator instance:$element->addValidator(new Zend_Validate_Alnum());

// Fully qualified class name:$element->addValidator('Zend_Validate_Alnum');

// Short validator name:$element->addValidator(‘Alnum’);$element->addValidator(‘alnum’);

Page 29: Zend framework 04 - forms

29

Adding Validators

If failing a particular validation should prevent later

Validators from firing, pass boolean true as thesecond parameter when adding a validator to theForm element:

$element->addValidator('alnum', true);

$element->addValidator('StringLength', false, array(6, 20));

Page 30: Zend framework 04 - forms

30

Standard available Validators

• Alnum• Alpha• Barcode• Between• Ccnum• Date• Digits• EmailAddress• Float• GreaterThan• Hex• Hostname• Identical• InArray• Int• Ip

• LessThan• NotEmpty• Regex• StringLength• Barcode_Ean13• Barcode_UpcA• File_Count• File_Exists• File_Extension• File_FilesSize• File_ImageSize• File_MimeType• File_NotExists• File_Size• File_Upload

Page 31: Zend framework 04 - forms

31

Custom error messages

Each Validator has one or more error messages

It is possible to set custom error messages for theValidator to use by passing it as an associative

arrayin the $options argument:

$element->addValidator(‘MyValidator',

false,

array(‘messages’,

array(‘myerror’ => ‘My message’,

‘error2’ => ‘Other msg.’)

));

Page 32: Zend framework 04 - forms

32

Validating an element

To validate an element simply call isValid():

if ($element->isValid($value)) {

// valid

}

else {

foreach ($element->getMessages() as $id => $message) {

echo "Validation failure '$id': $message\n";

}

}

* Remember that isValid() first filters the value!

Page 33: Zend framework 04 - forms

33

Custom Validators

Custom Validators can be created byimplementing the Zend_Validate_Interface

interface Zend_Validate_Interface

{

public function isValid($value);

public function getMessages();

public function getErrors();

}

Page 34: Zend framework 04 - forms

34

Custom Validators

• When you use the default way to implement errors and messages (recommended) you may also extend Zend_Validate_Abstract.

• You then only need to implement the isValid() method in you subclass, and set the error messages in the $_messageTemplates attribute.

Page 35: Zend framework 04 - forms

35

Custom Validator example

class MyValid_Float extends Zend_Validate_Abstract{

const FLOAT = 'float';

protected $_messageTemplates = array(self::FLOAT => "'%value%' is no floating point value"

);

public function isValid($value){

$this->_setValue($value);if (!is_float($value)) {

$this->_error();return false;

}return true;

}}

Page 36: Zend framework 04 - forms

36

Form validation

To validate a form, simply pass all data that needs

to be validated to the isValid() method:

$data = array(‘name’ => ‘my name’, ‘address’ => ‘my address’);

$form->isValid($data);

or

// $request contains Zend_Controller_Request_Http

$form->isValid($request->getPost());

Page 37: Zend framework 04 - forms

37

Partial Validation

Sometimes you only need to check a part of theform. In that case you can use isValidPartial(). Thiswill only run validations for the keys that are

presentin the provided array.

if ($form->isValidPartial($_POST)) {

// elements present all passed validations

}

else {

// one or more elements tested failed validations

}

Page 38: Zend framework 04 - forms

38

Partial Validation (AJAX)

A special case to use partial validation is when you

check a part of your form through AJAX. For this you

can use the processAjax() method.

It returns a JSON-formatted string of error messages

upon failure.

Page 39: Zend framework 04 - forms

39

Validation Context

It is possible to make a Validator ‘aware’ of not onlyit’s element, but also of other data passed to otherelements.

This is accomplished by providing this data in asecond argument:

$element->isValid($value, $context);

Zend_Form::isValid() passes the entire array of dataautomatically to this argument.

Page 40: Zend framework 04 - forms

40

Validation Context example

class My_Validate_PasswordConfirmation extends Zend_Validate_Abstract{

const NOT_MATCH = 'notMatch';protected $_messageTemplates = array(

self::NOT_MATCH => 'Password confirmation does not match');

public function isValid($value, $context = null){

$value = (string) $value;$this->_setValue($value);if (is_array($context)) {

if (isset($context['password_confirm'])&& ($value == $context['password_confirm'])) {return true;

}} elseif (is_string($context) && ($value == $context)) {

return true;}$this->_error(self::NOT_MATCH);return false;

}}

Page 41: Zend framework 04 - forms

41

Validator Chains

When you often have to perform the samevalidations in the same order you can create aValidation Chain (which is no more than a

Validatoritself):

$vChain = new Zend_Validate();

$vChain->addValidator(new Zend_Validate_StringLength(6, 12))

->addValidator(new Zend_Validate_Alnum());

$valid = $vChain->isValid($username);

Page 42: Zend framework 04 - forms

42

Displaying errors

Remember that by default the Errors Decorator was

added to the element?

So when the form is invalid, render it again:

if (!$form->isValid($_POST)) {

echo $form;

// or assign to the view object and render a view...

$this->view->form = $form;

return $this->render('form');

}

Page 43: Zend framework 04 - forms

43

Getting the data

Assuming your validations have passed, you canfetch the filtered values:

$values = $form->getValues();

If you need the unfiltered values at any point, use:

$unfiltered = $form->getUnfilteredValues();

Page 44: Zend framework 04 - forms

44

Adding it up: custom Elements

• Using all this information, it is now easy to create your own custom form elements. Simply extend the Zend_Form_Element class and add your own logic to it.

• The most common way to do this is by overriding the init() or loadDefaultDecorators() methods.

Page 45: Zend framework 04 - forms

45

Custom Elements example

class My_Element_Text extends Zend_Form_Element{

public function init(){

$this->addPrefixPath('My_Dec', 'My/Dec/', 'decorator')

->addFilters('StringTrim') ->addValidator('Regex',

false, array('/^[a-z0-9]{6,}$/i'))

->addDecorator('TextItem') ->setAttrib('size', 30) ->setAttrib('maxLength', 45) ->setAttrib('class', 'text');

}}

Page 46: Zend framework 04 - forms

46

Custom Elements

Be aware that it is possible to make multipleextensions.

In this way you can create a base class and extendfrom that:

Zend_Form_Element_Xhtml extends Zend_Form_Element

Zend_Form_Element_Text extends Zend_Form_Element_Xhtml

My_Textfield extends Zend_Form_Element_Text

My_Textfield_FirstName extends My_Textfield

My_Textfield_LastName extends My_Textfield

My_Textfield_Street extends My_Textfield

Page 47: Zend framework 04 - forms

47

Adding it up further: custom Forms

Just like Form elements, Forms can also besubclassed. This has several advantages:

• You can unit test forms• More control over individual elements• Re-use of form objects• Implement custom functionality

Page 48: Zend framework 04 - forms

48

Custom Forms example

class My_Form_Login extends Zend_Form{

public function init(){

$username = new My_Element_Username();$password = new My_Element_Password();$submit = new Zend_Form_Element_Submit('login');

$this->addElements(array($username,$password,$submit

));}

}

Page 49: Zend framework 04 - forms

49

Rendering form elements

In order to have even more control over your formelements, it is possible to render them individually ona View. This is useful if there is more separate

markupin the form:

<form action="<?php echo $this->escape($this->form-> getAction()); ?>" method="<?php echo $this->escape($this-> form->getMethod()); ?>" id="orderForm">

<?php echo $this->form->name; ?><p>Some additional text</p><?php echo $this->form->name; ?><div class=“special”>Some special markup</div><?php echo $this->form->name; ?><hr /></form>

Page 50: Zend framework 04 - forms

50

More possibilities

Not even all possibilities are mentioned:

• Usage of config files• Sub forms• Display groups• Form decorators• Internatiolaization• Etc.