Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 20-10-2015 15:26:41

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 65

Data binding des formulaires

Bonjour à tous,

j'ai encore un problème avec le data binding des formulaires...

J'expérimente pour l'instant doctrine et je me retrouve confronté à un problème lors de l'édition d'un de mes formulaires...

Pour faire simple, j'ai un formulaire qui comporte 3 fieldsets. Pour chacun de mes fieldset, j'ai comme constructeur :

Code:

[lang=php]
    public function __construct(ObjectManager $objectManager) {
        parent::__construct('holderPersonForm');
        $this->setHydrator(new DoctrineHydrator($objectManager));
        $this->setObject(new Person());
                // le new Object() est différent pour chaque constructeur
    }

J'ai le même constructeur pour mon form et au niveau de celui-ci, j'ajoute mes fieldsets comme ceci :

Code:

[lang=php]
    public function init() {
        $this->add([
                'name' => 'person',
                'type' => 'personFieldset',
                'options' => [
                        'label' => ucfirst('person'),
                        'use_as_base_fieldset' => true
                ],
                'attributes' => [
                        'id' => 'fieldset-person_group'
                ]
        ], [
                'priority' => -10
        ]);
        $this->add ( [ 
                'name' => 'address',
                'type' => 'AddressFieldset',
                'options' => [ 
                        'label' => ucfirst ( 'coordinates' )
                ],
                'attributes' => [ 
                        'id' => 'fieldset-address_group' 
                ] 
        ], [ 
                'priority' => - 20 
        ] );
        $this->add ( [ 
                'name' => 'user',
                'type' => 'UserFieldset',
                'options' => [ 
                        'label' => ucfirst ( 'user' )
                ],
                'attributes' => [ 
                        'id' => 'fieldset-user_group' 
                ] 
        ], [ 
                'priority' => - 30 
        ] );
    }

Au niveau de mon controller, je récupère les données comme ceci :

Code:

[lang=php]
public function editAction() {
     $id = $this->params()->fromRoute('id');
     $object = $this->mapper->find($id)
     $form = $this->getServiceLocator()->get('FormElementManager')->get('HolderPersonForm');
     $form->bind($object);
}

Bref, du gros classique !

Pour être plus précis, mon entity Person a une relation OneToOne avec Address et une relation OneToOne avec User.
Au niveau de ma variable $object, j'ai donc quelque chose comme ça :

Code:

[lang=php]
object(Person\Entity\Person)[569]
  private 'idperson' => int 50
  private 'title' => string 'M.' (length=2)
  private 'courtesy' => string '' (length=0)
  private 'firstname' => string 'xxxxxxxx' (length=6)
  private 'lastname' => string 'xxxxxxxxxxx' (length=9)
  private 'birthdate' => null
  private 'address_id' => int 32
  private 'user_id' => int 7
  private 'language' => string 'fr' (length=2)
  private 'acceptoffers' => int 1
  private 'address' => 
    object(DoctrineORMModule\Proxy\__CG__\Application\Entity\Address)[601]
      public '__initializer__' => 
        object(Closure)[578]
      public '__cloner__' => 
        object(Closure)[579]
      public '__isInitialized__' => boolean false
      private 'idaddress' (Application\Entity\Address) => int 32
      private 'address' (Application\Entity\Address) => null
      private 'address_2' (Application\Entity\Address) => null
      private 'postalcode' (Application\Entity\Address) => null
      private 'city' (Application\Entity\Address) => null
      private 'telephone' (Application\Entity\Address) => null
      private 'email' (Application\Entity\Address) => null
      private 'latitude' (Application\Entity\Address) => null
      private 'longitude' (Application\Entity\Address) => null
      private 'country_code_id' (Application\Entity\Address) => null
      private 'countryCode' (Application\Entity\Address) => null
  private 'user' => 
    object(DoctrineORMModule\Proxy\__CG__\User\Entity\User)[588]
      public '__initializer__' => 
        object(Closure)[593]
      public '__cloner__' => 
        object(Closure)[592]
      public '__isInitialized__' => boolean false
      private 'iduser' (User\Entity\User) => int 7
      private 'userid' (User\Entity\User) => null
      private 'password' (User\Entity\User) => null
      private 'salt' (User\Entity\User) => null
      private 'profile' (User\Entity\User) => null

Le data binding fonctionne plus ou moins bien. Je m'explique !
Dans la configuration actuelle de mon Form, avec le fieldset "personFieldset" comme base, les champs liés à l'entity Person se remplissent correctement (les fieldset Address et User) sont vides.
Par contre, si je ne défini pas mon fieldset Person comme base, j'ai exactement l'inverse : les champs liés à PersonFieldset sont vides alors que les autres sont remplit !!!

J'ai certainement loupé quelque chose mais quoi ?

Une idée ?

Merci d'avance,

Romain

Hors ligne

 

#2 20-10-2015 16:26:10

tdutrion
Administrateur
Lieu: Dijon, Paris, Edinburgh
Date d'inscription: 23-12-2009
Messages: 614
Site web

Re: Data binding des formulaires

Bonjour,

Ton objet Person contient un objet Address et un objet User.

Ton form contient un fieldset Person, un fieldset Address et un fieldset User.

Il faut donc modifier ton form principal pour que tu puisse soit binder ton Person dessus (supprimer le fieldset person et tout mettre dans le principal), soit mettre les deux autres fieldset dans Person.

Hors ligne

 

#3 21-10-2015 08:45:23

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 65

Re: Data binding des formulaires

Bonjour Théocrite,

si je comprends bien ce que tu veux dire, il faut que je supprime mon fieldset Person dans mon Form pour avoir quelque chose du style :

Code:

[lang=php]

public function init() {
        $this->add([
                'name' => 'id',
                'type' => 'Hidden',
        ]);
        $this->add([
                'name' => 'firstname',
                'type' => 'text',
        ]);
        $this->add([
                'name' => 'lastname',
                'type' => 'text',
        ]);
                // et je continue comme ça pour tous mes champs de Person ?
        $this->add ( [ 
                'name' => 'address',
                'type' => 'AddressFieldset',
                'options' => [ 
                        'label' => ucfirst ( 'coordinates' )
                ],
                'attributes' => [ 
                        'id' => 'fieldset-address_group' 
                ] 
        ], [ 
                'priority' => - 20 
        ] );
        $this->add ( [ 
                'name' => 'user',
                'type' => 'UserFieldset',
                'options' => [ 
                        'label' => ucfirst ( 'user' )
                ],
                'attributes' => [ 
                        'id' => 'fieldset-user_group' 
                ] 
        ], [ 
                'priority' => - 30 
        ] );
    }

Hors ligne

 

#4 21-10-2015 11:23:14

tdutrion
Administrateur
Lieu: Dijon, Paris, Edinburgh
Date d'inscription: 23-12-2009
Messages: 614
Site web

Re: Data binding des formulaires

As-tu testé ça ? Ça devrait marcher normalement.

L'autre méthode (juste le Person fieldset dans le form principal, et les autres fieldset dans le Person, en utilisant Person comme fieldset de base, ça te permet de mettre ton submit, un CSRF et tout dans le form principal). J'ai tendance à préférer cette solution.

Fais des tests et dis moi ce qui marche ou pas !

Hors ligne

 

#5 21-10-2015 11:49:45

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 65

Re: Data binding des formulaires

Effectivement, j'ai testé le code précédent et ça fonctionne.
Par contre, j'ai déjà un fieldset Person avec uniquement les champs liés à cette entity mais je trouve que c'est un peut se répéter pour pas grand chose (j'utilise ce fieldset dans une autre action).

En revanche, je ne vois pas trop ce que tu veux dire à propos de l'autre méthode...
Il s'agirait de mettre le code précédent dans un fieldset et de le charger dans un form en précisant l'option 'use_as_base_fieldset', c'est bien ça ?

Hors ligne

 

#6 21-10-2015 13:23:27

tdutrion
Administrateur
Lieu: Dijon, Paris, Edinburgh
Date d'inscription: 23-12-2009
Messages: 614
Site web

Re: Data binding des formulaires

Tu dois pouvoir probablement ajouter les deux fieldset en réutilisant le fieldset Person que tu as déjà. Une sorte de mix des deux solutions du coup...

Dans ta classe Form, tu ajoutes ton Person (pas $this->add, créée une variable $person = new Person() - ou mieux utilises une injection ici).

Tu as maintenant $person, tu peux donc faire $person->add() pour ajouter tes deux fieldsets. Fais aussi un $person-> useAsBaseFieldset(true); pour le définir comme base pour ton form.

Enfin, ajoutes tes inputs de gestion de form (csrf, submit).

Et voilà, ça devrait être tout beau !

Hors ligne

 

#7 21-10-2015 13:52:30

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 65

Re: Data binding des formulaires

Ah ok !
Je vois bien ce que tu veux dire !

Merci pour ces précisions wink

Hors ligne

 

#8 22-10-2015 10:11:13

Orkin
Administrateur
Lieu: Paris
Date d'inscription: 09-12-2011
Messages: 1261

Re: Data binding des formulaires

RomainG a écrit:

Code:

[lang=php]
public function editAction() {
     $id = $this->params()->fromRoute('id');
     $object = $this->mapper->find($id)
     $form = $this->getServiceLocator()->get('FormElementManager')->get('HolderPersonForm');
     $form->bind($object);
}

Hello, par contre ça c'est pas propre du tout. On ne doit pas utiliser le service locator dans les contrôleurs. Tu dois injecter ton formulaire dans le contrôleur en utilisant une factory. Vaut mieux prendre cette habitude dès maintenant puisque dans le ZF3 il n'y aura plus le service locator dans le contrôleur et donc tu ne pourras plus faire ça wink.

Théocrite a écrit:

Tu dois pouvoir probablement ajouter les deux fieldset en réutilisant le fieldset Person que tu as déjà. Une sorte de mix des deux solutions du coup...

Dans ta classe Form, tu ajoutes ton Person (pas $this->add, créée une variable $person = new Person() - ou mieux utilises une injection ici).

Tu as maintenant $person, tu peux donc faire $person->add() pour ajouter tes deux fieldsets. Fais aussi un $person-> useAsBaseFieldset(true); pour le définir comme base pour ton form.

Enfin, ajoutes tes inputs de gestion de form (csrf, submit).

Et voilà, ça devrait être tout beau !

Personnellement je préfère faire autrement. Enfin ça revient au même mais je trouve que ça évite d'écrire trop de code. En gros ce qu'il faut se dire c'est que les fieldset doivent représenter tes entités doctrine. Donc pour ça tu vas avoir ton fieldset Person qui lui même contiendra tes 2 autres fieldset (tu peux en ajouter un comme si tu faisais un input de type text, ça fonctionne de la même manière). De cette façon tu vas avoir la même structure entre ton entité et ton fieldset.
Ensuite rien de plus simple dans ton formulaire tu ajoutes le fieldset Person et voila le tour est joué. Si jamais tu as besoin d'utiliser que ton fieldset Adress tu peux faire un autre formulaire qui contiendra uniquement le fieldset Adress et si jamais tu veux utiliser le fieldset Person sans Adress (qui est dedans) tu utilises les validationGroup. Tu as 2 manières de faire. Soit tu gères via un paramètre dans ton formulaire et en fonction de cette valeur tu changes le validationGroup soit tu créés un autre formulaire avec le bon validationGroup directement wink.

Hors ligne

 

#9 22-10-2015 10:48:38

RomainG
Membre
Date d'inscription: 10-06-2015
Messages: 65

Re: Data binding des formulaires

Orkin a écrit:

Hello, par contre ça c'est pas propre du tout. On ne doit pas utiliser le service locator dans les contrôleurs. Tu dois injecter ton formulaire dans le contrôleur en utilisant une factory. Vaut mieux prendre cette habitude dès maintenant puisque dans le ZF3 il n'y aura plus le service locator dans le contrôleur et donc tu ne pourras plus faire ça wink.

Oui effectivement, c'est pas propre du tout, je le concède...
J'injecte généralement mes forms grâce à une factory

Orkin a écrit:

Personnellement je préfère faire autrement. Enfin ça revient au même mais je trouve que ça évite d'écrire trop de code. En gros ce qu'il faut se dire c'est que les fieldset doivent représenter tes entités doctrine. Donc pour ça tu vas avoir ton fieldset Person qui lui même contiendra tes 2 autres fieldset (tu peux en ajouter un comme si tu faisais un input de type text, ça fonctionne de la même manière). De cette façon tu vas avoir la même structure entre ton entité et ton fieldset.
Ensuite rien de plus simple dans ton formulaire tu ajoutes le fieldset Person et voila le tour est joué. Si jamais tu as besoin d'utiliser que ton fieldset Adress tu peux faire un autre formulaire qui contiendra uniquement le fieldset Adress et si jamais tu veux utiliser le fieldset Person sans Adress (qui est dedans) tu utilises les validationGroup. Tu as 2 manières de faire. Soit tu gères via un paramètre dans ton formulaire et en fonction de cette valeur tu changes le validationGroup soit tu créés un autre formulaire avec le bon validationGroup directement

C'est au final ce que j'ai fait !

Hors ligne

 

Pied de page des forums

Propulsé par PunBB
© Copyright 2002–2005 Rickard Andersson
Traduction par punbb.fr

Graphisme réalisé par l'agence Rodolphe Eveilleau
Développement par Kitpages