Disregard Inputs, Acquire Zend_Form

3,021 views

Published on

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.

Published in: Technology
  • Be the first to comment

Disregard Inputs, Acquire Zend_Form

  1. 1. Disregard InputsAcquire Zend_Form
  2. 2. Daniel CousineauInteractive Software Engineer @ RAPP@dcousineauhttp://dcousineau.com/dcousineau@gmail.com
  3. 3. Zend_Acl Zend_Gdata Zend_Search_LuceneZend_Amf Zend_Http Zend_SerializerZend_Application Zend_InfoCard Zend_ServerZend_Auth Zend_Json Zend_ServiceZend_Barcode Zend_Layout Zend_SessionZend_Cache Zend_Ldap Zend_SoapZend_Captcha Zend_Loader Zend_TagZend_Cloud Zend_Locale Zend_TestZend_CodeGenerator Zend_Log Zend_TextZend_Config Zend_Mail Zend_TimeSyncZend_Config_Writer Zend_Markup Zend_ToolZend_Console_Getopt Zend_Measure Zend_Tool_FrameworkZend_Controller Zend_Memory Zend_Tool_ProjectZend_Currency Zend_Mime Zend_TranslateZend_Date Zend_Navigation Zend_UriZend_Db Zend_Oauth Zend_ValidateZend_Debug Zend_OpenId Zend_VersionZend_Dojo Zend_Paginator Zend_ViewZend_Dom Zend_Pdf Zend_WildfireZend_Exception Zend_ProgressBar Zend_XmlRpcZend_Feed Zend_Queue ZendX_Console_Process_UnixZend_File Zend_Reflection ZendX_JQueryZend_Filter Zend_RegistryZend_Form Zend_Rest
  4. 4. Zend_Acl Zend_Gdata Zend_Search_LuceneZend_Amf Zend_Http Zend_SerializerZend_Application Zend_InfoCard Zend_ServerZend_Auth Zend_Json Zend_ServiceZend_Barcode Zend_Layout Zend_SessionZend_Cache Zend_Ldap Zend_SoapZend_Captcha Zend_Loader Zend_TagZend_Cloud Zend_Locale Zend_TestZend_CodeGenerator Zend_Log Zend_TextZend_Config Zend_Mail Zend_TimeSyncZend_Config_Writer Zend_Markup Zend_ToolZend_Console_Getopt Zend_Measure Zend_Tool_FrameworkZend_Controller Zend_Memory Zend_Tool_ProjectZend_Currency Zend_Mime Zend_TranslateZend_Date Zend_Navigation Zend_UriZend_Db Zend_Oauth Zend_ValidateZend_Debug Zend_OpenId Zend_VersionZend_Dojo Zend_Paginator Zend_ViewZend_Dom Zend_Pdf Zend_WildfireZend_Exception Zend_ProgressBar Zend_XmlRpcZend_Feed Zend_Queue ZendX_Console_Process_UnixZend_File Zend_Reflection ZendX_JQueryZend_Filter Zend_RegistryZend_Form Zend_Rest
  5. 5. I CAN HAZ HAI WERLD!?!http://snipsnsnailsandpuppydogtails.blogspot.com/2010/05/introducing-captain-jack-sparrow-and.html
  6. 6. Zend_Form$form = new Zend_Form();$form->setAction(/path/to/action) ->setMethod(post) ->setAttrib(id, FORMID);
  7. 7. Render Form$output = $form->render();<?php print $form; ?><form id="FORMID" enctype="application/x-www-form-urlencoded" action="/path/to/action" method="post"> <dl class="zend_form"></dl></form>
  8. 8. Add Elements$form->addElement(text, hello, array( label => Oh Hai Werld!, required => true,));$element = new Zend_Form_Element_Text(hello);$element->setLabel(Oh Hai Werld!) ->setRequired(true);$form->addElement($element, hello);
  9. 9. 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>
  10. 10. 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
  11. 11. Handle Inputif (!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}
  12. 12. 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(), ),));
  13. 13. 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(), ),));
  14. 14. COOL BEST PRACTICES BRO
  15. 15. 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, )); }}
  16. 16. Extend Zend_Form Object$form = new Zend_Form();$form = new Namespace_Form_HelloWorld();
  17. 17. Store Forms By Module
  18. 18. STYLING
  19. 19. Decorator PatternBASICALLY: Wrappers for renderingElement has list of decorators Render Decorator n Send output to Decorator n+1 Repeat until no more decorators
  20. 20. Decorator Pattern 2 “levels” of decorators Form-Level Element-Level Form level decorator “FormElements” loops through each element and triggers their render
  21. 21. FormElements DECORATOR ELEMENT DECORATE DECORATE ELEMENT DECORATE ... ELEMENT
  22. 22. 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
  23. 23. Default Element Decorators$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> <dd id=”...”> <p class=”description”></p> RENDER ELEMENT <ul><li>ERRORS</li></ul>
  24. 24. PLEASE EXPLAIN TO MEHOW BEST PRACTICES FITS WITH PHILOSORAPTOR
  25. 25. 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
  26. 26. Use render() SparinglyOverriding Zend_Form::render() is temptingUseful for bulk-altering element decoratorsJust be very judicial
  27. 27. CUSTOM ELEMENTS
  28. 28. Extend Zend_Form_ElementOverride loadDefaultDecorators() Usually copy original, but replace ViewHelper with custom decoratorAdd flags and features to your hearts content
  29. 29. Create DecoratorOverride render() Use an existing render from, say, HtmlTag, as a starting pointUse array notation on any sub-fields e.g. “fullyQualifiedName[foo]”, etc
  30. 30. 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
  31. 31. 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);
  32. 32. Basic Example
  33. 33. Custom Elementclass 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)); } }}
  34. 34. 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; } }}
  35. 35. Complex Example
  36. 36. 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) {} //...}
  37. 37. 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; } //...}
  38. 38. 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()); } } //...}
  39. 39. class Namespace_Form_Decorator_Date extends Zend_Form_Decorator_Abstract {Custom Decorator const DEFAULT_DISPLAY_FORMAT = %year% / %month% / %day%; //... public function render($content) { $element = $this->getElement(); if (!$element instanceof FormElementDate) 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; } }}
  40. 40. BEST PRACTICESY U NO USE THEM!?
  41. 41. Mimic NamespaceMimic Zend_Form’s name spacing Namespace_Form_Decorator_ Zend_Form_Decorator_If you aren’t already, mimic Zend’s structure (PEARstyle) Namespace_Form_Decorator_Date → Namespace/ Form/Decorator/Date.php
  42. 42. Use Prefix Paths Or NotEither directly reference the custom classes throughoutyour entire project, or don’tDon’t jump back and forth
  43. 43. http://joind.in/2981

×