44
Disregard Inputs Acquire Zend_Form

Disregard Inputs, Acquire Zend_Form

Embed Size (px)

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.

Citation preview

Page 1: Disregard Inputs, Acquire Zend_Form

Disregard Inputs

Acquire Zend_Form

Page 2: Disregard Inputs, Acquire Zend_Form

Daniel CousineauInteractive Software Engineer @ RAPP@dcousineauhttp://dcousineau.com/[email protected]

Page 3: Disregard Inputs, Acquire Zend_Form
Page 4: Disregard Inputs, Acquire Zend_Form

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

Page 5: Disregard Inputs, Acquire Zend_Form

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

Page 7: Disregard Inputs, Acquire Zend_Form

Zend_Form

$form = new Zend_Form();

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

Page 8: Disregard Inputs, Acquire Zend_Form

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();

Page 9: Disregard Inputs, Acquire Zend_Form

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,));

Page 10: Disregard Inputs, Acquire Zend_Form

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>

Page 11: Disregard Inputs, Acquire Zend_Form

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

Page 12: Disregard Inputs, Acquire Zend_Form

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}

Page 13: Disregard Inputs, Acquire Zend_Form

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(), ),));

Page 14: Disregard Inputs, Acquire Zend_Form

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(), ),));

Page 15: Disregard Inputs, Acquire Zend_Form

COOL BEST PRACTICES BRO

Page 16: Disregard Inputs, Acquire Zend_Form

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', )); }}

Page 17: Disregard Inputs, Acquire Zend_Form

Extend Zend_Form Object

$form = new Namespace_Form_HelloWorld();

$form = new Zend_Form();

Page 18: Disregard Inputs, Acquire Zend_Form

Store Forms By Module

Page 19: Disregard Inputs, Acquire Zend_Form

STYLING

Page 20: Disregard Inputs, Acquire Zend_Form

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

Page 21: Disregard Inputs, Acquire Zend_Form

Decorator Pattern

2 “levels” of decorators

Form-Level

Element-Level

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

Page 22: Disregard Inputs, Acquire Zend_Form

ELEMENT

...

ELEMENT

DECORATEDECORATE

DECORATE

FormElements DECORATOR

ELEMENT

Page 23: Disregard Inputs, Acquire Zend_Form

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

Page 24: Disregard Inputs, Acquire Zend_Form

$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

Page 25: Disregard Inputs, Acquire Zend_Form

PLEASE EXPLAIN TO ME

HOW BEST PRACTICES FITS WITH PHILOSORAPTOR

Page 26: Disregard Inputs, Acquire Zend_Form

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

Page 27: Disregard Inputs, Acquire Zend_Form

Use render() Sparingly

Overriding Zend_Form::render() is tempting

Useful for bulk-altering element decorators

Just be very judicial

Page 28: Disregard Inputs, Acquire Zend_Form

CUSTOM ELEMENTS

Page 29: Disregard Inputs, Acquire Zend_Form

Extend Zend_Form_Element

Override loadDefaultDecorators()

Usually copy original, but replace ViewHelper with custom decorator

Add flags and features to your hearts content

Page 30: Disregard Inputs, Acquire Zend_Form

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

Page 31: Disregard Inputs, Acquire Zend_Form

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

Page 32: Disregard Inputs, Acquire Zend_Form

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');

Page 33: Disregard Inputs, Acquire Zend_Form

Basic Example

Page 34: Disregard Inputs, Acquire Zend_Form

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')); } }}

Page 35: Disregard Inputs, Acquire Zend_Form

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; } }}

Page 36: Disregard Inputs, Acquire Zend_Form

Complex Example

Page 37: Disregard Inputs, Acquire Zend_Form

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) {} //...}

Page 38: Disregard Inputs, Acquire Zend_Form

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; } //...}

Page 39: Disregard Inputs, Acquire Zend_Form

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()); } } //...}

Page 40: Disregard Inputs, Acquire Zend_Form

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; } }}

Page 41: Disregard Inputs, Acquire Zend_Form

Y U NO USE THEM!?

BEST PRACTICES

Page 42: Disregard Inputs, Acquire Zend_Form

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

Page 43: Disregard Inputs, Acquire Zend_Form

Use Prefix Paths Or Not

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

Don’t jump back and forth

Page 44: Disregard Inputs, Acquire Zend_Form

http://joind.in/2981