Tirer parti des décorateurs de Zend_Form

Embed Size (px)

DESCRIPTION

Comment tirer parti des décorateurs de Zend_Form ?

Citation preview

  • 1. Tirer parti des dcorateurs Zend_FormMickal Perraud ContributeurZend Framework Responsable documentation franaise

2. Qu'est-ce qu'un dcorateur ? 3. Dans Zend_Form

  • Combinaison des patrons de conceptionDecoratoretStrategy

4. PatrondeconceptionDcorateur Enprogrammationoriente objet, le patron de conception dcorateur est un motif qui permet l'ajout dynamique de fonctionnalits un objet existant. Wikipedia, Dcorateur_(patron_de_conception) 5. 6. Deux techniques principales

  • Dfinir uneinterface laquelle tous les objets concrets et les dcorateurs adhrent
    • Souvent, les dcorateurs implmenteront une interface additionnelle
  • Duck-typing
    • Utilise une mthode/proprit dans le dcorateur pour proxier vers l'objet dcor

7. interface Window { public function isOpen(); public function open(); public function close (); } 8. classStandardWindow implements Window { protected $_open = false; public function isOpen() { return $this ->_open; } public function open() { if (! $this ->_open) { $this ->_open = true;} } public function close () { if ( $this ->_open) { $this ->_open = false; } } } 9. classLockedWindow implements Window { protected $_window ; public function __construct(Window $window ){ $this ->_window = $window ; $this ->_window-> close (); } public function isOpen() { return false; } public function open() { throw new Exception( 'Cannot open locked windows' );} public function close () { $this ->_window-> close ();} } 10. classLockedWindow { protected$_window ; public function __construct(Window $window ) { $this ->_window = $window ; $this ->_window-> close (); } publicfunctionisOpen() {returnfalse; } public function __call( $method , $args ) { if (! method_exists ( $this ->_window, $method )) { throw new Exception( 'Invalid method' ); } return $this ->_window-> $method (); } } 11. Patrondeconception Stratgie Un patron de conception particulier, dans lequel les algorithmes peuvent tre slectionns lors de l'excution. Wikipedia, Strategy_pattern 12. 13. classWindow { public $strategy ; public function open() { $this -> $strategy ->open(); } } interface OpenStrategy { public function open(); } 14. classRaiseStrategy implements OpenStrategy { public function open() { } } class LeverStrategy implements OpenStrategy { public function open() { } } 15. Crer votre premier dcorateur 16. L'interface

  • Zend_Form_Decorator_Interface
    • __construct($options = null); 17. setElement($element); 18. getElement(); 19. setOptions(array $options); 20. setConfig(Zend_Config $config); 21. setOption($key, $value); 22. getOption($key); 23. getOptions(); 24. removeOption($key); 25. clearOptions(); 26. render($content);

27. L'interface

  • Ce qu'il est ncessaire de retenir :
    • render($content);

28. Un dcorateur simple pour un champ texte

  • Va rendre un label 29. Va rendre le champ texte 30. Va rcuprer les mta-donnes partir de l'lment et les utiliser pour dfinir l'affichage gnr

31. class My_Decorator_SimpleInput extends Zend_Form_Decorator_Abstract { protected $_format = '%s' . '' ; public function render( $content ) { $element = $this ->getElement(); $name = htmlentities ( $element ->getFullyQualifiedName()); $label = htmlentities ( $element ->getLabel()); $id = htmlentities ( $element ->getId()); $value = htmlentities ( $element ->getValue()); $markup = sprintf ( $this ->_format, $name , $label , $id , $name , $value ); return $markup ; } } 32. $decorator= new My_Decorator_SimpleInput(); $element = new Zend_Form_Element( 'foo' , array ( 'label' => 'Foo' , 'belongsTo' => 'bar' , 'value' => 'test' , 'decorators' => array ( $decorator ), )); $element= new Zend_Form_Element( 'foo' ,array ( 'label' => 'Foo' , 'belongsTo' => 'bar' , 'value' => 'test' , 'prefixPath' => array ( 'decorator' => array ( 'My_Decorator' => 'path/to/decorators/' , )), 'decorators' => array ( 'SimpleInput' ), )); 33. Foo 34. O en sommes-nous ?

  • R-utilisation 35. chappement automatique 36. Slection des attributs que vous souhaitez propager et afficher au moment de l'excution

37. Superposer les dcorateurs 38. L'argument $content

  • Utilis pour agrger les sorties des multiples dcorateurs 39. Des dcorateurs individuels peuvent tre spcialiss dans la cration d'affichages lis certaines mtadonnes de l'lment 40. L'affichage final est le produit de tous les dcorateurs

41. Dcorateurs par dfaut

  • ViewHelper utilise une aide de vue pour effectuer le rendu de l'lment de formulaire lui-mme 42. Description effectue le rendu de la description de l'lment, si besoin 43. Errors effectue le rendu des erreurs de validation, si besoin 44. HtmlTag enveloppe tout le contenu gnr dans une balise 45. Label utilise une aide de vue pour effectuer le rendu du libell de l'lment; l'ajoute devant le contenu agrg

46. 47. 48. 49. 50. 51. Comment superposer les dcorateurs ?

  • Utilisez l'option placement 52. Choississez de :
    • Ajouter aprs le contenu fourni (APPEND) 53. Ajouter avant le contenu fourni (PREPEND) 54. Remplacer le contenu fourni (REPLACE)
  • Utiliser un placement par dfaut sain; les options vous permettront de le surcharger

55. classMy_Decorator_SimpleInputextendsZend_Form_Decorator_Abstract { protected $_format = '' ; public function render( $content ) { $element = $this ->getElement(); $name = htmlentities ( $element ->getFullyQualifiedName()); $id = htmlentities ( $element ->getId()); $value = htmlentities ( $element ->getValue()); $markup = sprintf ( $this ->_format, $id , $name , $value ); // On gre le placement ici... return $markup ; } } 56. classMy_Decorator_SimpleLabelextendsZend_Form_Decorator_Abstract { protected $_format = '%s' ; public function render( $content ) { $element = $this ->getElement(); $id = htmlentities ( $element ->getId()); $label = htmlentities ( $element ->getLabel()); $markup = sprint( $this ->_format, $id , $label ); // On gre le placement ici... return $markup ; } } 57. $placement=$this ->getPlacement(); $separator = $this ->getSeparator(); switch ( $placement ) { case self::PREPEND: return $markup.$separator.$content ; case self::APPEND: default: return $content . $separator . $markup ; } switch ( $placement ) { case self::APPEND: return $content.$separator.$markup ; case self::PREPEND: default: return $markup.$separator.$content ; } 58. $element= new Zend_Form_Element( 'foo' ,array ( 'label' => 'Foo' , 'belongsTo' => 'bar' , 'value' => 'test' , 'prefixPath' => array ( 'decorator' => array ( 'My_Decorator' => 'path/to/decorators/' , )), 'decorators' => array ( 'SimpleInput' , 'SimpleLabel' , ), )); 59. $element= new Zend_Form_Element( 'foo' ,array ( 'label' => 'Foo' , 'belongsTo' => 'bar' , 'value' => 'test' , 'prefixPath' => array ( 'decorator' => array ( 'My_Decorator' => 'path/to/decorators/' , )), 'decorators' => array ( 'SimpleInput' array ( 'SimpleLabel' , array ( 'placement' => 'append' )), ), )); 60. Rendre les dcorateurs individuellement 61. Pourquoi ?

  • Simplement parfois, parce que le balisage est trop complexe pour tre assembl par superposition 62. Vos designers peuvent vouloir avoir plus de visibilit sur ce qui est rendu

63. Comment ? $decorator=$element ->getDecorator( 'SimpleInput' ); echo $decorator ->render( '' ); Facile : echo $element ->getDecorator( 'SimpleInput' ) ->render( '' ); Plus facile : echo $element ->renderSimpleInput(); Encore plus facile : 64.

65.

/ /

66. Crer des lments composs 67. Exemple : une date d'anniversaire

  • Stocke la date en interne sous la forme d'un timestamp 68. Pour une question de confort, on demande l'utilisateur de renseigner indpendamment le jour, le mois et l'anne 69. mais typiquement ces dcorateurs reprsentent un seul lment de formulaire

70. Cration de l'lment

  • Accepte les valeurs de type entier 71. Accepte les valeurs sous la forme de tableau avec des cls jour/mois/anne 72. Accepte les valeurs sous forme de chane 73. Possde des accesseurs pour chaque segment de la date (jours, mois et anne)

74. classMy_Form_Element_DateextendsZend_Form_Element_Xhtml { public function setValue( $value ) { if ( is_int ( $value )) { $this ->_value = new DateTime( date ( 'Y-m-d' , $value )); } elseif ( is_string ( $value )) { $this ->_value = new DateTime( $value ); } elseif ( is_array ( $value )) { $this ->_value = new DateTime(); $this ->_value->setDate( $value [ 'year' ], $value [ 'month' ], $value [ 'day' ] ); } else { throw new Exception( 'Invalid date value provided' ); } return $this ; } public function getDay() { } public function getMonth() { } public function getYear() { } } 75. Cration d'un dcorateur

  • Ajoute un proxy duck-type vers l'lment 76. S'assure de la prsence d'une vue 77. Rcupre les mta-donnes partir de l'lment 78. Fournit les mta-donnes aux aides de vues existantes pour crer le balisage

79. classMy_Form_Decorator_DateextendsZend_Form_Decorator_Abstract { public function render( $content ) { $element = $this ->getElement(); if (! $element instanceof My_Form_Element_Date) { return $content ; } $view = $element ->getView(); if (! $view instanceof Zend_View_Interface) { return $content ; } $day = $element ->getDay(); $month = $element ->getMonth(); $year = $element ->getYear(); $name = $element ->getFullyQualifiedName(); // ... } } 80. classMy_Form_Decorator_DateextendsZend_Form_Decorator_Abstract { public function render( $content ) { // ... $params = array ( 'size' => 2, 'maxlength' => 2); $yearParams = array ( 'size' => 4, 'maxlength' => 4); $markup = $view ->formText( $name . '[day]' , $day , $params ) . ' / '. $view ->formText( $name . '[month]' , $month , $params ) . ' / '. $view ->formText( $name . '[year]' , $year , $yearParams ); // Placement et valeur de retour ... } } 81. Mettre jour l'lment

  • S'assure que l'lment sait o il peut trouver ces dcorateurs 82. Spcifie les dcorateurs par dfaut

83. classMy_Form_Element_DateextendsZend_Form_Element_Xhtml { // ... public function __construct( $spec , $options = null ) { $this ->addPrefixPath( 'My_Form_Decorator' , 'My/Form/Decorator' , 'decorator' ); parent::__construct( $spec , $options ); } // ... } 84. classMy_Form_Element_Date extendsZend_Form_Element_Xhtml { // ... public function loadDefaultDecorators() { if ( $this ->loadDefaultDecoratorsIsDisabled()) { return ; } if (empty( $decorators = $this ->getDecorators() )) { $this ->addDecorator( 'Date' ) // ... ; } } // ... } 85. Maintenant on l'utilise ! $d= new My_Form_Element_Date( 'dateOfBirth' ); $d ->setLabel( 'Date of Birth: ' ) ->setView(new Zend_View()); // Ceux-ci sont quivalents : $d ->setValue( '20 April 2009' ); $d ->setValue( array ( 'year' => '2009' , 'month' => '04' , 'day' => '20' )); 86. Date of Birth: / / 87. Conclusion 88. Qu'avons-nous couvert ?

  • Ce que sont les dcorateurs, et par quelle approche Zend_Form les utilise 89. Comment crer vos propres dcorateurs 90. Comment superposer les dcorateurs 91. Comment rendre individuellement les dcorateurs 92. Comment crer des lments constitus d'entres composes

93. Pour aller plus loin

  • Zend Framework Workshop (DPC 2010) : http://www.slideshare.net/weierophinney/zend-framework-workshop-4480868 94. Crer un visuel personnalis en utilisant Zend_Form_Decorator : http://framework.zend.com/manual/fr/zend.form.decorators.html

95. Merci !

  • Zend Framework: http://framework.zend.com/ 96. Twitter/IRC nick: mikaelkael 97. Mon blog: http://mikaelkael.fr/