Zend framework 04 - forms
-
Upload
tricode -
Category
Technology
-
view
637 -
download
0
description
Transcript of Zend framework 04 - forms
Zend Framework
4. Forms
Tricode Professional Serviceswww.tricode.nl
Date: 27-02-2009Author: Marcel Blok
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
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 ?>
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
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
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');
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
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
9
Form element plugins
Plugins are used for
• Decorators• Validators• Filters
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" />
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
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.
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')),
));
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>
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);
}
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.
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;
}
}
}
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
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');
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.
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
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');
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
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);
}
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;
}
}
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?
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
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’);
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));
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
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.’)
));
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!
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();
}
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.
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;
}}
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());
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
}
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.
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.
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;
}}
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);
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');
}
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();
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.
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');
}}
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
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
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
));}
}
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>
50
More possibilities
Not even all possibilities are mentioned:
• Usage of config files• Sub forms• Display groups• Form decorators• Internatiolaization• Etc.