disregard inputs, acquire zend_form

Post on 12-May-2015

2.636 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Learn in-depth Zend_Form techniques to automate and power your applications forms, with or without using Zend Framework. Learn everything from setup of a form to custom elements and organizational best practices.

TRANSCRIPT

Disregard Inputs

Acquire Zend_Form

Daniel CousineauInteractive Software Engineer @ RAPP@dcousineauhttp://dcousineau.com/dcousineau@gmail.com

Zend_AclZend_AmfZend_ApplicationZend_AuthZend_BarcodeZend_CacheZend_CaptchaZend_CloudZend_CodeGeneratorZend_ConfigZend_Config_WriterZend_Console_GetoptZend_ControllerZend_CurrencyZend_DateZend_DbZend_DebugZend_DojoZend_DomZend_ExceptionZend_FeedZend_FileZend_FilterZend_Form

Zend_GdataZend_HttpZend_InfoCardZend_JsonZend_LayoutZend_LdapZend_LoaderZend_LocaleZend_LogZend_MailZend_MarkupZend_MeasureZend_MemoryZend_MimeZend_NavigationZend_OauthZend_OpenIdZend_PaginatorZend_PdfZend_ProgressBarZend_QueueZend_ReflectionZend_RegistryZend_Rest

Zend_Search_LuceneZend_SerializerZend_ServerZend_ServiceZend_SessionZend_SoapZend_TagZend_TestZend_TextZend_TimeSyncZend_ToolZend_Tool_FrameworkZend_Tool_ProjectZend_TranslateZend_UriZend_ValidateZend_VersionZend_ViewZend_WildfireZend_XmlRpcZendX_Console_Process_UnixZendX_JQuery

Zend_AclZend_AmfZend_ApplicationZend_AuthZend_BarcodeZend_CacheZend_CaptchaZend_CloudZend_CodeGeneratorZend_ConfigZend_Config_WriterZend_Console_GetoptZend_ControllerZend_CurrencyZend_DateZend_DbZend_DebugZend_DojoZend_DomZend_ExceptionZend_FeedZend_FileZend_FilterZend_Form

Zend_GdataZend_HttpZend_InfoCardZend_JsonZend_LayoutZend_LdapZend_LoaderZend_LocaleZend_LogZend_MailZend_MarkupZend_MeasureZend_MemoryZend_MimeZend_NavigationZend_OauthZend_OpenIdZend_PaginatorZend_PdfZend_ProgressBarZend_QueueZend_ReflectionZend_RegistryZend_Rest

Zend_Search_LuceneZend_SerializerZend_ServerZend_ServiceZend_SessionZend_SoapZend_TagZend_TestZend_TextZend_TimeSyncZend_ToolZend_Tool_FrameworkZend_Tool_ProjectZend_TranslateZend_UriZend_ValidateZend_VersionZend_ViewZend_WildfireZend_XmlRpcZendX_Console_Process_UnixZendX_JQuery

Zend_Form

$form = new Zend_Form();

$form->setAction('/path/to/action') ->setMethod('post') ->setAttrib('id', 'FORMID');

Render Form

<form id="FORMID" enctype="application/x-www-form-urlencoded" action="/path/to/action" method="post"> <dl class="zend_form"></dl></form>

<?php print $form; ?>

$output = $form->render();

Add Elements

$element = new Zend_Form_Element_Text('hello');$element->setLabel('Oh Hai Werld!') ->setRequired(true);

$form->addElement($element, 'hello');

$form->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'required' => true,));

Add Elements

<dl> <dt id="hello-label"> <label for="hello" class="required"> Oh Hai Werld! </label> </dt> <dd id="hello-element"> <input type="text" name="hello" id="hello" value=""> </dd></dl>

Zend_Form_Element_ButtonZend_Form_Element_CaptchaZend_Form_Element_CheckboxZend_Form_Element_FileZend_Form_Element_HiddenZend_Form_Element_HashZend_Form_Element_ImageZend_Form_Element_MultiCheckboxZend_Form_Element_MultiselectZend_Form_Element_RadioZend_Form_Element_ResetZend_Form_Element_SelectZend_Form_Element_SubmitZend_Form_Element_TextZend_Form_Element_Textarea

Handle Input

if (!empty($_POST) && $form->isValid($_POST)) { $values = $form->getValues(); //FORM IS VALID}

if ($this->getRequest()->isPost() && $form->isValid($this->getRequest()->getParams())) { $values = $form->getValues(); //FORM IS VALID}

Add Validation

$form->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'validators' => array( 'Alnum' //@see Zend_Validate_Alnum ),));

$form->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'validators' => array( new Zend_Validate_Alnum(), ),));

Add Filters

$form->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'filters' => array( 'StringTrim' //@see Zend_Filter_StringTrim ),));

$form->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'filters' => array( new Zend_Filter_StringTrim(), ),));

COOL BEST PRACTICES BRO

Extend Zend_Form Objectclass Namespace_Form_HelloWorld extends Zend_Form { public function init() { /* Form Elements & Other Definitions Here ... */ $this->addElement('text', 'hello', array( 'label' => 'Oh Hai Werld!', 'required' => true, 'validators' => array( 'Alnum', ), )); $this->addElement('submit', 'submit', array( 'label' => 'I Can Haz Submit', )); }}

Extend Zend_Form Object

$form = new Namespace_Form_HelloWorld();

$form = new Zend_Form();

Store Forms By Module

STYLING

Decorator Pattern

BASICALLY: Wrappers for rendering

Element has list of decorators

Render Decorator n

Send output to Decorator n+1

Repeat until no more decorators

Decorator Pattern

2 “levels” of decorators

Form-Level

Element-Level

Form level decorator “FormElements” loops through each element and triggers their render

ELEMENT

...

ELEMENT

DECORATEDECORATE

DECORATE

FormElements DECORATOR

ELEMENT

Default Form Decorators$this->addDecorator('FormElements') ->addDecorator('HtmlTag', array( 'tag' => 'dl', 'class' => 'zend_form') ) ->addDecorator('Form');

<form>

<dl class=”zend_form”>

Loop & Render Form Elements

$this->addDecorator('ViewHelper') ->addDecorator('Errors') ->addDecorator('Description', array('tag' => 'p', 'class' => 'description')) ->addDecorator('HtmlTag', array( 'tag' => 'dd', 'id' => array('callback' => $getId) )) ->addDecorator('Label', array('tag' => 'dt'));

<dt>LABEL</dt>

Default Element Decorators

<dd id=”...”>

<p class=”description”></p>

<ul><li>ERRORS</li></ul>

RENDER ELEMENT

PLEASE EXPLAIN TO ME

HOW BEST PRACTICES FITS WITH PHILOSORAPTOR

Integrate Early

If you’re using custom decorators, set the prefix paths EARLY. Constructor OR first few lines of init()

Optionally have an application-wide parent Form class that all other forms extend

Here you can do common things like set the prefix paths

Use render() Sparingly

Overriding Zend_Form::render() is tempting

Useful for bulk-altering element decorators

Just be very judicial

CUSTOM ELEMENTS

Extend Zend_Form_Element

Override loadDefaultDecorators()

Usually copy original, but replace ViewHelper with custom decorator

Add flags and features to your hearts content

Create Decorator

Override render()

Use an existing render from, say, HtmlTag, as a starting point

Use array notation on any sub-fields

e.g. “fullyQualifiedName[foo]”, etc

Handle/Validate Input

Override setValue() and getValue()

setValue() will receive the value from $_FORM (including sub-arrays, etc)

Override isValid() with caution:

isValid() calls setValue()

Possibly create custom Zend_Validate_ and attach in the custom element

Using

$form->getPluginLoader(Zend_Form::DECORATOR) ->addPrefixPath('Namespace_Form_Decorator', '/path/to/decorators'); $form->getPluginLoader(Zend_Form::ELEMENT) ->addPrefixPath('Namespace_Form_Element', 'path/to/elements');

Basic Example

Custom Element

class Namespace_Form_Element_Markup extends Zend_Form_Element_Xhtml{ public function isValid($value, $context = null) { return true; } public function loadDefaultDecorators() { if ($this->loadDefaultDecoratorsIsDisabled()) { return; } $decorators = $this->getDecorators(); if (empty($decorators)) { $this->addDecorator(new Namespace_Form_Decorator_Markup()) ->addDecorator('HtmlTag', array('tag' => 'dd')); } }}

Custom Decoratorclass Namespace_Form_Decorator_Markup extends Zend_Form_Decorator_Abstract { public function render($content) { $element = $this->getElement(); if (!$element instanceof Namespace_Form_Element_Markup) return $content; $name = $element->getName(); $separator = $this->getSeparator(); $placement = $this->getPlacement();

$markup = '<div id="' . $name . '" class="markup">' . $element->getValue() . '</div>';

switch ($placement) { case self::PREPEND: return $markup . $separator . $content; case self::APPEND: default: return $content . $separator . $markup; } }}

Complex Example

Custom Elementclass Namespace_Form_Element_Date extends Zend_Form_Element_Xhtml { const DEFAULT_DATE_FORMAT = '%year%-%month%-%day%'; //... public function loadDefaultDecorators(){ if ($this->loadDefaultDecoratorsIsDisabled()) return; $this->addDecorator(new Namespace_Form_Decorator_Date()) ->addDecorator('Errors') ->addDecorator('Description', array('tag' => 'p', 'class' => 'description')) ->addDecorator('HtmlTag', array( 'tag' => 'dd', 'id' => $this->getName() . '-element') ) ->addDecorator('Label', array('tag' => 'dt')); } public function getDateFormat() {} public function setDateFormat($dateFormat) {} //...}

Custom Elementclass Namespace_Form_Element_Date extends Zend_Form_Element_Xhtml { //... public function setValue($value) { if (is_array($value)) { $year = !empty($value['year']) ? $value['year'] : null; $month = !empty($value['month']) ? $value['month'] : null; $day = !empty($value['day']) ? $value['day'] : 1; if ($year && $month) { $date = new DateTime(); $date->setDate((int)$year, (int)$month, (int) $day); $date->setTime(0, 0, 0); $this->setAutoInsertNotEmptyValidator(false); $this->_value = $date; } } else { $this->_value = $value; }

return $this; } //...}

Custom Elementclass Namespace_Form_Element_Date extends Zend_Form_Element_Xhtml { //... public function getValue() { switch ($this->getReturnType()) { case self::RETURN_TYPE_ARRAY: if ($this->_value === null) return array('year' => null, 'month' => null, 'day' => null);

$date = array( 'year' => date('Y', $this->_value->getTimestamp()), 'month' => date('m', $this->_value->getTimestamp()), 'day' => date('d', $this->_value->getTimestamp()) ); array_walk_recursive($date, array($this, '_filterValue')); return $date; default: throw new Zend_Form_Element_Exception('Unknown return type: ' . $this->getReturnType()); } } //...}

Custom Decoratorclass Namespace_Form_Decorator_Date extends Zend_Form_Decorator_Abstract { const DEFAULT_DISPLAY_FORMAT = '%year% / %month% / %day%'; //... public function render($content) { $element = $this->getElement(); if (!$element instanceof Form\Element\Date) return $content;

$view = $element->getView(); if (!$view instanceof Zend_View_Interface) throw new Zend_Form_Decorator_Exception('View object is required'); //... $markup = str_replace( array('%year%', '%month%', '%day%'), array( $view->formSelect($name . '[year]', $year, $params, $years), $view->formSelect($name . '[month]', $month, $params, $months), $view->formSelect($name . '[day]', $day, $params, $days), ), $this->displayFormat );

switch ($this->getPlacement()) { case self::PREPEND: return $markup . $this->getSeparator() . $content; case self::APPEND: default: return $content . $this->getSeparator() . $markup; } }}

Y U NO USE THEM!?

BEST PRACTICES

Mimic Namespace

Mimic Zend_Form’s name spacing

Namespace_Form_Decorator_ ↔

Zend_Form_Decorator_

If you aren’t already, mimic Zend’s structure (PEAR style)

Namespace_Form_Decorator_Date → Namespace/Form/Decorator/Date.php

Use Prefix Paths Or Not

Either directly reference the custom classes throughout your entire project, or don’t

Don’t jump back and forth

http://joind.in/2981

top related