IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Zend_Form PHP Discussion :

Décorateurs, la misère 2.0


Sujet :

Zend_Form PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Avatar de Nowwis
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2009
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2009
    Messages : 406
    Par défaut Décorateurs, la misère 2.0
    Bonjour à tous,

    Comme beaucoup, je galère au niveau des décorators de formulaire...

    Je sais pas pourquoi, mais pour plus de lisibilité, j'aimerais créer un truc du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    <form enctype="multipart/form-data" method="post" action="">
        <fieldset>
    		<legend>Informations personelles</legend>
    		<label>Nom : <input type="text"></label>
    		<label>Email : <input type="text"></label>
        </fieldset>
     
        <fieldset>
    		<legend>Localisation</legend>
    		<label>Région : 
    			<select name="regionVehicule" id="regionVehicule" helper="formSelect">
    				<option value="0" label=""></option>
    				<option value="1" label="Alsace">Alsace</option>
    				<option value="2" label="Aquitaine">Aquitaine</option>
    				<option value="3" label="Auvergne">Auvergne</option>
    				<option value="4" label="Basse Normandie">Basse Normandie</option>
    			</select>
    		</label>
    		<label>Département : 
    			<select name="departementVehicule" id="departementVehicule" helper="formSelect" disabled="disabled">
    				<option value="0" label=""></option>
    			</select>
    		</label>
    	</fieldset>
    	<input type="submit" name="Envoyer" id="Envoyer" value="Envoyer">
    </form>
    (J'ai enlevé certain élément mais globalement ça ressemble à ça).

    J'aimerais créer des décorateurs simple pour pouvoir les transformer rapidement (mon intégrateur me demande souvent d'ajouter une class sur un label ou un input par exemple, il faut que cela reste simple...)

    J'ai déjà dérivé mes élements (Text, File, Select, Submit)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <?php 
        class App_Form_Element_Text extends Zend_Form_Element_Text
        {
            public function __construct($spec, $options = null)
            {
                parent::__construct($spec, $options = null);
                $this->clearDecorators();
                $decorator = new App_Form_Decorator_FormVide();
                $this->addDecorator($decorator);
            }
        }
    Et ainsi créé un décorateur FormVide :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    <?php
        /*
         * Sort un formulaire au format :
         * <label class="obligatoire"> Label : <input type="text" name="label" /></label>
         */
        class App_Form_Decorator_FormVide extends Zend_Form_Decorator_Abstract
        {
     
            public function buildInput()
            {
                $element = $this->getElement();
                $helper = $element->helper;
                return $element->getView()->$helper($element->getName(), $element->getValue(), $element->getAttribs(), $element->options);
            }
     
            public function buildLabel()
            {
                $element = $this->getElement();
                $label = $element->getLabel();
                $class = "";
                if($element->isRequired())
                    $class='class="obligatoire"';
                return "<label ".$class.">".$label.$this->buildInput()."</label>";
            }
     
            public function buildErrors()
            {
                $element = $this->getElement();
                $messages = $element->getMessages();
                $retour = "";
     
                if(empty($messages)) 
                    return;
                foreach($messages as $message)
                {
                        $retour .= $message."<br />";
                }
                return $retour;
            }
     
            public function buildDescription()
            {
                return;
            }
     
            public function render($content)
            {
                $label = $this->buildLabel();
                $errors = $this->buildErrors();
                $description = $this->buildDescription();
                return $content.$label.$errors.$description;
            }
        }
    Mais impossible de faire la même chose pour le type File par exemple. Donc je me demande si je suis sur la bonne voix.

    Merci d'avance !

  2. #2
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Par défaut
    En principe, lorsqu'on dérive un élément pour lui définir d'autres décorateurs, on utilise la méthode loadDefaultDecorators() pour définir ces décorateurs:
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php 
        class App_Form_Element_Text extends Zend_Form_Element_Text
        {
            public function loadDefaultDecorators()
            {
    	    if ($this->loadDefaultDecoratorsIsDisabled()) {
                    return;
                }
                $decorator = new App_Form_Decorator_FormVide();
                $this->addDecorator($decorator);
            }
        }
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  3. #3
    Membre très actif
    Avatar de Nowwis
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2009
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2009
    Messages : 406
    Par défaut
    Bonjour,

    Merci pour ce détail, je vais donc modifier mon code pour utiliser le load au lieu du __construct.

    Je n'ai pas trouvé la possibilité d'entourer par exemple mon input d'un label, c'est vraiment le seul moyen que j'ai. Y'en a t'il d'autre ? (car si je veux changer la class du label par exemple, je ne peux pas...)

    Merci d'avance !

  4. #4
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Par défaut
    Le problème de ton décorateur, c'est que son champ d'action est trop large ; le propre d'un décorateur est d'être très spécialisé, pour être le plus modulaire possible.

    Si j'ai bien compris ton problème, c'est que la classe CSS de ton label varie selon que l'élément est déclaré obligatoire ou pas. Je vois deux manières d'y parvenir facilement :

    a) Créer un décorateur App_Form_Decorator_Label descendant de Zend_Form_Decorator_Label, et redéfinir la méthode getClass()

    b) Dans la méthode render() de ton App_Form_Element_Text, définir l'option 'class' du décorateur 'Label' attaché à l'élément

    Personnellement je privilégierais la première solution.
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

  5. #5
    Membre très actif
    Avatar de Nowwis
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2009
    Messages
    406
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Somme (Picardie)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2009
    Messages : 406
    Par défaut
    D'accord je vois maintenant la configuration du Label par défault.

    De plus, je vois "placement" par défault en prepend.

    Y'a t'il moyen d'entouré l'input ?

    Actuellement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <label for="name">Nom : </label><input name="name" />
    Ce que j'aimerais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <label><input /></label>
    (Je situe le soucis sur la méthode render de App_Form_Decorator_Label mais j'ai du mal à voir exactement comme faire pour personnaliser.
    Apparemment le label est utilisé par HtmlTag pour s'afficher, si j'ai bien saisie.

    Merci d'avance.

  6. #6
    Expert confirmé
    Avatar de GrandFather
    Inscrit en
    Mai 2004
    Messages
    4 587
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Mai 2004
    Messages : 4 587
    Par défaut
    La doc de Zend liste les décorateurs déclarés par défaut pour chaque élément : http://framework.zend.com/manual/en/...nts.decorators

    En gros il y a déjà tout ce dont tu as besoin, il te faut juste un décorateur Label spécifique.
    Citation Envoyé par Nowwis Voir le message
    Apparemment le label est utilisé par HtmlTag pour s'afficher, si j'ai bien saisie.
    Non non, 'Label' et 'HtmlTag' sont des décorateurs distincts. Le décorateur Label utilise effectivement un HtmlTag en interne, mais uniquement pour inclure le label dans la balise définie par l'option 'tag' si celle-ci est utilisée (ce qui n'est pas ton cas).

    Pour que l'input soit inclus dans le label, il faut redéfinir la méthode render() héritée de Zend_Form_Decorator_Label en l'adaptant :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
        public function render($content)
        {
            $element = $this->getElement();
            $view    = $element->getView();
            if (null === $view) {
                return $content;
            }
     
            $label     = $this->getLabel();
            $separator = $this->getSeparator();
            $placement = $this->getPlacement();
            $tag       = $this->getTag();
            $id        = $this->getId();
            $class     = $this->getClass();
            $options   = $this->getOptions();
     
     
            if (empty($label) && empty($tag)) {
                return $content;
            }
     
            if (!empty($label)) {
                // On ne peut pas utiliser le view helper Label dans ce contexte
                // puisqu'on veut inclure $content à l'intérieur du <label>
                // $options['class'] = $class;
                // $label = $view->formLabel($element->getFullyQualifiedName(), trim($label), $options);
               $label = "<label class=\"$class\">" . $content . "</label>";
            } else {
                $label = '*';
            }
     
            if (null !== $tag) {
                require_once 'Zend/Form/Decorator/HtmlTag.php';
                $decorator = new Zend_Form_Decorator_HtmlTag();
                $decorator->setOptions(array('tag' => $tag,
                                             'id'  => $this->getElement()->getName() . '-label'));
     
                $label = $decorator->render($label);
            }
     
    //        switch ($placement) {
    //            case self::APPEND:
    //                return $content . $separator . $label;
    //            case self::PREPEND:
    //                return $label . $separator . $content;
    //        }
            return $label;
        }

    C'est vite fait mal fait, mais dans le principe c'est ce qu'il faut faire.

    Deux choses à prendre en compte:

    1) Si tu lis le lien que j'ai posté plus haut, tu t'apercevras que le décorateur 'Label' est le dernier décorateur par défaut, ce qui voudra dire qu'avec ton label "custom" il englobera tout le rendu de l'élément, erreurs comprises (décorateur 'Errors'). Il faut en tenir compte dans ton CSS. Si c'est problématique, si les erreurs doivent s'afficher après le label, il faudra redéfinir les décorateurs par défaut (dans loadDefaultDecorators()) en changeant leur ordre.

    2) Pour que ce soit ton décorateur personnalisé plutôt que celui fourni par Zend qui soit utilisé, il faut signaler à ton élément où le rechercher :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    class App_Form_Element_Text extends Zend_Form_Element_Text
    {
     
    	public function init()
    	{
    		$this->addPrefixPath('App_Form_Decorator', 'App/Form/Decorator/', 'decorator');		
    	}
    FAQ XML
    ------------
    « Le moyen le plus sûr de cacher aux autres les limites de son savoir est de ne jamais les dépasser »
    Giacomo Leopardi

Discussions similaires

  1. [gcc me fait des misères]
    Par GyZmoO dans le forum Autres éditeurs
    Réponses: 4
    Dernier message: 11/05/2006, 19h43
  2. Misère avec 1 objet (?)
    Par qi130 dans le forum Langage
    Réponses: 2
    Dernier message: 19/03/2006, 22h55
  3. Misère d'encode ...
    Par a028762 dans le forum XML/XSL et SOAP
    Réponses: 2
    Dernier message: 02/10/2005, 21h21
  4. XMLC_SecurityLevel = Global me fais des misères
    Par mchicoix dans le forum XMLRAD
    Réponses: 2
    Dernier message: 03/02/2005, 21h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo