SlideShare a Scribd company logo
Disregard Inputs




Acquire Zend_Form
Daniel Cousineau
Interactive Software Engineer @ RAPP
@dcousineau
http://dcousineau.com/
dcousineau@gmail.com
Disregard Inputs, Acquire Zend_Form
Zend_Acl              Zend_Gdata         Zend_Search_Lucene
Zend_Amf              Zend_Http          Zend_Serializer
Zend_Application      Zend_InfoCard      Zend_Server
Zend_Auth             Zend_Json          Zend_Service
Zend_Barcode          Zend_Layout        Zend_Session
Zend_Cache            Zend_Ldap          Zend_Soap
Zend_Captcha          Zend_Loader        Zend_Tag
Zend_Cloud            Zend_Locale        Zend_Test
Zend_CodeGenerator    Zend_Log           Zend_Text
Zend_Config            Zend_Mail          Zend_TimeSync
Zend_Config_Writer     Zend_Markup        Zend_Tool
Zend_Console_Getopt   Zend_Measure       Zend_Tool_Framework
Zend_Controller       Zend_Memory        Zend_Tool_Project
Zend_Currency         Zend_Mime          Zend_Translate
Zend_Date             Zend_Navigation    Zend_Uri
Zend_Db               Zend_Oauth         Zend_Validate
Zend_Debug            Zend_OpenId        Zend_Version
Zend_Dojo             Zend_Paginator     Zend_View
Zend_Dom              Zend_Pdf           Zend_Wildfire
Zend_Exception        Zend_ProgressBar   Zend_XmlRpc
Zend_Feed             Zend_Queue         ZendX_Console_Process_Unix
Zend_File             Zend_Reflection     ZendX_JQuery
Zend_Filter           Zend_Registry
Zend_Form             Zend_Rest
Zend_Acl              Zend_Gdata         Zend_Search_Lucene
Zend_Amf              Zend_Http          Zend_Serializer
Zend_Application      Zend_InfoCard      Zend_Server
Zend_Auth             Zend_Json          Zend_Service
Zend_Barcode          Zend_Layout        Zend_Session
Zend_Cache            Zend_Ldap          Zend_Soap
Zend_Captcha          Zend_Loader        Zend_Tag
Zend_Cloud            Zend_Locale        Zend_Test
Zend_CodeGenerator    Zend_Log           Zend_Text
Zend_Config            Zend_Mail          Zend_TimeSync
Zend_Config_Writer     Zend_Markup        Zend_Tool
Zend_Console_Getopt   Zend_Measure       Zend_Tool_Framework
Zend_Controller       Zend_Memory        Zend_Tool_Project
Zend_Currency         Zend_Mime          Zend_Translate
Zend_Date             Zend_Navigation    Zend_Uri
Zend_Db               Zend_Oauth         Zend_Validate
Zend_Debug            Zend_OpenId        Zend_Version
Zend_Dojo             Zend_Paginator     Zend_View
Zend_Dom              Zend_Pdf           Zend_Wildfire
Zend_Exception        Zend_ProgressBar   Zend_XmlRpc
Zend_Feed             Zend_Queue         ZendX_Console_Process_Unix
Zend_File             Zend_Reflection     ZendX_JQuery
Zend_Filter           Zend_Registry
Zend_Form             Zend_Rest
I CAN HAZ




                                       HAI WERLD!?!
http://snipsnsnailsandpuppydogtails.blogspot.com/2010/05/introducing-captain-jack-sparrow-and.html
Zend_Form
$form = new Zend_Form();

$form->setAction('/path/to/action')
     ->setMethod('post')
     ->setAttrib('id', 'FORMID');
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>
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');
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_Button
Zend_Form_Element_Captcha
Zend_Form_Element_Checkbox
Zend_Form_Element_File
Zend_Form_Element_Hidden
Zend_Form_Element_Hash
Zend_Form_Element_Image
Zend_Form_Element_MultiCheckbox
Zend_Form_Element_Multiselect
Zend_Form_Element_Radio
Zend_Form_Element_Reset
Zend_Form_Element_Select
Zend_Form_Element_Submit
Zend_Form_Element_Text
Zend_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 Object
class 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 Zend_Form();


$form = new Namespace_Form_HelloWorld();
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
FormElements DECORATOR

    ELEMENT       DECORATE
                  DECORATE
    ELEMENT
                  DECORATE
       ...

    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
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>
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 Decorator
class 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 Element
class 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 Element
class 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 Element
class 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());
        }
    }
    //...
}
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;
        }
    }
}
BEST PRACTICES




Y U NO USE THEM!?
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

More Related Content

PPT
Zend framework 04 - forms
ODP
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
PDF
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
PDF
Error Reporting in ZF2: form messages, custom error pages, logging
PPT
Jquery presentation
PDF
Dealing with Legacy PHP Applications
PDF
Leveraging Symfony2 Forms
PPT
Framework
Zend framework 04 - forms
Zend_Form to the Rescue - A Brief Introduction to Zend_Form
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
Error Reporting in ZF2: form messages, custom error pages, logging
Jquery presentation
Dealing with Legacy PHP Applications
Leveraging Symfony2 Forms
Framework

What's hot (20)

PDF
Everything you always wanted to know about forms* *but were afraid to ask
PPTX
Hacking Your Way To Better Security - Dutch PHP Conference 2016
PDF
Dig Deeper into WordPress - WD Meetup Cairo
PDF
Dealing With Legacy PHP Applications
PPS
Implementing access control with zend framework
PPTX
Сергей Иващенко - Meet Magento Ukraine - Цены в Magento 2
PPTX
Quality code by design
KEY
Unit testing zend framework apps
PDF
Introduction to Zend Framework web services
PDF
Gail villanueva add muscle to your wordpress site
PDF
Refactoring using Codeception
PDF
The new form framework
PPTX
jQuery from the very beginning
PPT
Система рендеринга в Magento
PDF
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
PPTX
Top 5 Magento Secure Coding Best Practices
PPT
Propel sfugmd
PPT
Os Nixon
PDF
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
PDF
50 Laravel Tricks in 50 Minutes
Everything you always wanted to know about forms* *but were afraid to ask
Hacking Your Way To Better Security - Dutch PHP Conference 2016
Dig Deeper into WordPress - WD Meetup Cairo
Dealing With Legacy PHP Applications
Implementing access control with zend framework
Сергей Иващенко - Meet Magento Ukraine - Цены в Magento 2
Quality code by design
Unit testing zend framework apps
Introduction to Zend Framework web services
Gail villanueva add muscle to your wordpress site
Refactoring using Codeception
The new form framework
jQuery from the very beginning
Система рендеринга в Magento
QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API Fi...
Top 5 Magento Secure Coding Best Practices
Propel sfugmd
Os Nixon
QA Lab: тестирование ПО. Яков Крамаренко: "KISS Automation"
50 Laravel Tricks in 50 Minutes
Ad

Viewers also liked (9)

PPT
Delicious
PPT
Podcasting Power Point
PPT
Get ready for FRC 2015: Intro to Java 5 through 8 updates and Eclipse
PDF
شرح خطوات التسجيل علي موقع Delicious
PPT
NI FIRST Robotics Controller Training
PPT
Podcasting Power Point
KEY
NOSQL101, Or: How I Learned To Stop Worrying And Love The Mongo!
PPT
Podcasting Power Point
Delicious
Podcasting Power Point
Get ready for FRC 2015: Intro to Java 5 through 8 updates and Eclipse
شرح خطوات التسجيل علي موقع Delicious
NI FIRST Robotics Controller Training
Podcasting Power Point
NOSQL101, Or: How I Learned To Stop Worrying And Love The Mongo!
Podcasting Power Point
Ad

Similar to Disregard Inputs, Acquire Zend_Form (20)

DOCX
Zend framework 2.0
PDF
Zend Framework Form: Mastering Decorators
PDF
Zend Framework 2 Patterns
KEY
Zend Framework Study@Tokyo #2
PPTX
Zend Framework Workshop
KEY
Zend framework: Getting to grips (ZF1)
KEY
Webinar: Zend framework Getting to grips (ZF1)
PPTX
Getting up & running with zend framework
PPTX
Getting up and running with Zend Framework
PDF
Zend framework 1.10.x English
PDF
A quick start on Zend Framework 2
PPT
PHPBootcamp - Zend Framework
PPTX
Zend framework
KEY
Extending ZF & Extending With ZF
PDF
ZF2 Presentation @PHP Tour 2011 in Lille
PPTX
Extending php (7), the basics
PPTX
Php Extensions for Dummies
PDF
Zend Framework 2 Components
Zend framework 2.0
Zend Framework Form: Mastering Decorators
Zend Framework 2 Patterns
Zend Framework Study@Tokyo #2
Zend Framework Workshop
Zend framework: Getting to grips (ZF1)
Webinar: Zend framework Getting to grips (ZF1)
Getting up & running with zend framework
Getting up and running with Zend Framework
Zend framework 1.10.x English
A quick start on Zend Framework 2
PHPBootcamp - Zend Framework
Zend framework
Extending ZF & Extending With ZF
ZF2 Presentation @PHP Tour 2011 in Lille
Extending php (7), the basics
Php Extensions for Dummies
Zend Framework 2 Components

Recently uploaded (20)

PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Empathic Computing: Creating Shared Understanding
PPT
Teaching material agriculture food technology
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PPTX
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PPTX
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Machine learning based COVID-19 study performance prediction
PPTX
Big Data Technologies - Introduction.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Empathic Computing: Creating Shared Understanding
Teaching material agriculture food technology
“AI and Expert System Decision Support & Business Intelligence Systems”
ACSFv1EN-58255 AWS Academy Cloud Security Foundations.pptx
Building Integrated photovoltaic BIPV_UPV.pdf
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Spectral efficient network and resource selection model in 5G networks
Reach Out and Touch Someone: Haptics and Empathic Computing
Understanding_Digital_Forensics_Presentation.pptx
20250228 LYD VKU AI Blended-Learning.pptx
VMware vSphere Foundation How to Sell Presentation-Ver1.4-2-14-2024.pptx
Programs and apps: productivity, graphics, security and other tools
MYSQL Presentation for SQL database connectivity
Chapter 3 Spatial Domain Image Processing.pdf
Machine learning based COVID-19 study performance prediction
Big Data Technologies - Introduction.pptx
Encapsulation_ Review paper, used for researhc scholars
The Rise and Fall of 3GPP – Time for a Sabbatical?

Disregard Inputs, Acquire Zend_Form

  • 2. Daniel Cousineau Interactive Software Engineer @ RAPP @dcousineau http://dcousineau.com/ dcousineau@gmail.com
  • 4. Zend_Acl Zend_Gdata Zend_Search_Lucene Zend_Amf Zend_Http Zend_Serializer Zend_Application Zend_InfoCard Zend_Server Zend_Auth Zend_Json Zend_Service Zend_Barcode Zend_Layout Zend_Session Zend_Cache Zend_Ldap Zend_Soap Zend_Captcha Zend_Loader Zend_Tag Zend_Cloud Zend_Locale Zend_Test Zend_CodeGenerator Zend_Log Zend_Text Zend_Config Zend_Mail Zend_TimeSync Zend_Config_Writer Zend_Markup Zend_Tool Zend_Console_Getopt Zend_Measure Zend_Tool_Framework Zend_Controller Zend_Memory Zend_Tool_Project Zend_Currency Zend_Mime Zend_Translate Zend_Date Zend_Navigation Zend_Uri Zend_Db Zend_Oauth Zend_Validate Zend_Debug Zend_OpenId Zend_Version Zend_Dojo Zend_Paginator Zend_View Zend_Dom Zend_Pdf Zend_Wildfire Zend_Exception Zend_ProgressBar Zend_XmlRpc Zend_Feed Zend_Queue ZendX_Console_Process_Unix Zend_File Zend_Reflection ZendX_JQuery Zend_Filter Zend_Registry Zend_Form Zend_Rest
  • 5. Zend_Acl Zend_Gdata Zend_Search_Lucene Zend_Amf Zend_Http Zend_Serializer Zend_Application Zend_InfoCard Zend_Server Zend_Auth Zend_Json Zend_Service Zend_Barcode Zend_Layout Zend_Session Zend_Cache Zend_Ldap Zend_Soap Zend_Captcha Zend_Loader Zend_Tag Zend_Cloud Zend_Locale Zend_Test Zend_CodeGenerator Zend_Log Zend_Text Zend_Config Zend_Mail Zend_TimeSync Zend_Config_Writer Zend_Markup Zend_Tool Zend_Console_Getopt Zend_Measure Zend_Tool_Framework Zend_Controller Zend_Memory Zend_Tool_Project Zend_Currency Zend_Mime Zend_Translate Zend_Date Zend_Navigation Zend_Uri Zend_Db Zend_Oauth Zend_Validate Zend_Debug Zend_OpenId Zend_Version Zend_Dojo Zend_Paginator Zend_View Zend_Dom Zend_Pdf Zend_Wildfire Zend_Exception Zend_ProgressBar Zend_XmlRpc Zend_Feed Zend_Queue ZendX_Console_Process_Unix Zend_File Zend_Reflection ZendX_JQuery Zend_Filter Zend_Registry Zend_Form Zend_Rest
  • 6. I CAN HAZ HAI WERLD!?! http://snipsnsnailsandpuppydogtails.blogspot.com/2010/05/introducing-captain-jack-sparrow-and.html
  • 7. Zend_Form $form = new Zend_Form(); $form->setAction('/path/to/action') ->setMethod('post') ->setAttrib('id', 'FORMID');
  • 8. 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>
  • 9. 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');
  • 10. 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>
  • 12. 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 }
  • 13. 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(), ), ));
  • 14. 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(), ), ));
  • 16. Extend Zend_Form Object class 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', )); } }
  • 17. Extend Zend_Form Object $form = new Zend_Form(); $form = new Namespace_Form_HelloWorld();
  • 18. Store Forms By Module
  • 20. 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
  • 21. Decorator Pattern 2 “levels” of decorators Form-Level Element-Level Form level decorator “FormElements” loops through each element and triggers their render
  • 22. FormElements DECORATOR ELEMENT DECORATE DECORATE ELEMENT DECORATE ... ELEMENT
  • 23. 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
  • 24. 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>
  • 25. PLEASE EXPLAIN TO ME HOW BEST PRACTICES FITS WITH PHILOSORAPTOR
  • 26. 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
  • 27. Use render() Sparingly Overriding Zend_Form::render() is tempting Useful for bulk-altering element decorators Just be very judicial
  • 29. Extend Zend_Form_Element Override loadDefaultDecorators() Usually copy original, but replace ViewHelper with custom decorator Add flags and features to your hearts content
  • 30. 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
  • 31. 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
  • 32. 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');
  • 34. 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')); } } }
  • 35. Custom Decorator class 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; } } }
  • 37. Custom Element class 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) {} //... }
  • 38. Custom Element class 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; } //... }
  • 39. Custom Element class 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()); } } //... }
  • 40. 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; } } }
  • 41. BEST PRACTICES Y U NO USE THEM!?
  • 42. 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
  • 43. Use Prefix Paths Or Not Either directly reference the custom classes throughout your entire project, or don’t Don’t jump back and forth