Zend FR

Consultez la FAQ sur le ZF avant de poster une question

Vous n'êtes pas identifié.

#1 23-01-2014 14:38:56

Splyf
Membre
Date d'inscription: 24-10-2013
Messages: 115

méthode "populate" et association

Bonjour,

Voici ce que je cherche à faire:

Prenons l'entité simplifier suivante:

Code:

[lang=php]class Categorie {

    /**
     * @var integer
     *
     * @ORM\etc....
     */
    private $catId;

    /**
     * @var string
     *
     * @ORM\etc...
     */
    private $catLib;

   
    /**
     * @var \Catalogue\Entity\Mesure
     *
     * @ORM\ManyToOne(targetEntity="Catalogue\Entity\Mesure")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="Cat_mesure", referencedColumnName="Me_id", nullable=true)
     * })
     */
    private $catMesure;

(l'entité Mesure représente des unité de mesure, kg, L, ect.)

je me suis fait dans l'entité Categorie un méthode populate comme ceci:

Code:

[lang=php]public function populate($data = array()) {
        $this->catId = ((isset($data['Cat_id']) ? $data['Cat_id'] : $this->catId));
        $this->catLib = ((isset($data['Cat_lib']) ? $data['Cat_lib'] : $this->catLib));
}

Mais pour la variable $cateMesure, comment faire?
j'ai fait ceci:

Code:

[lang=php]public function populate($em, $data = array()) {
        $this->catId = ((isset($data['Cat_id']) ? $data['Cat_id'] : $this->catId));
        $this->catLib = ((isset($data['Cat_lib']) ? $data['Cat_lib'] : $this->catLib));

        if (isset($data['Cat_mesure'])) {
            if (!is_object($data['Cat_mesure']))
                $mesure = $em->getRepository('Catalogue\Entity\Mesure')->find($data['Cat_mesure']);
            else
                $mesure = $data['Cat_mesure'];
        $this->setCatMesure($mesure);
 }

Tout cela avec comme objectif principal de bien comprendre doctrine ^^.
Passé l' EntityManager en parametre d'une entité est bien moche mais c'est pour vous faire comprendre ce que je souhaite faire...
N'y a til pas une méthode native qui me ferai sa?
En suite, avec la notion de "detached entity", est-ce que ceci peut avoir une utilité autre que dans un insert  ou je cherche midi a 14h?

ex:

Code:

[lang=php]function insertCategorie(){
...
...
$data  = $request->getPost()->toArray();
$categorie = new Categorie;
$categorie->populate($data);
$em->persist($categorie);
$em->flush();
}

Hors ligne

 

#2 23-01-2014 14:49:09

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

Re: méthode "populate" et association

Salut, effectivement tu cherches midi à 14h00. Il y a les hydrator qui sont là pour ça et le font très bien tout seul. Et si tu le fais vraiment bien ton formulaire te retournera déjà une entité remplie ($form->getData()) plutôt qu'un tableau.

Là en plus sur ton insertCategorie tu récupères directement les données post sans utiliser le filtre et la validation du formulaire. Donc pas du tout sécurisé tu dois au moins utiliser un inputFilter (si tu n'utilises pas les formulaires, genre pour de l'ajax).

Du coup dans ta couche service tu aurais plus qu'à faire un truc du genre :

Code:

[lang=php]
public function insertCategorie($categorie) {
$em->persist($categorie);
$em->flush()
}

Hors ligne

 

#3 23-01-2014 16:07:41

Splyf
Membre
Date d'inscription: 24-10-2013
Messages: 115

Re: méthode "populate" et association

Bin voui justement, je fait sa en ajax big_smile

C'est ptet pas une bonne idée pour commencé a assimilé Zend  mais tout mes backoffice le sont jusqu'ici alors autant chercher a reproduire ce que je fait déjà plutôt que régresser d'un pts de vue fonctionnel ^^. (mais tkt sa me pause aucun souci niveau debug, jai déjà fait le tour niveau ajax / zf2).

Du coup oui, je n'utilisant pas de forme, je cherchai a "remplir" mes entité avant de les validée...je vois que c'était pas la bonne aproche ^^.

Du coup je vais chercher du coté des hydrator! Merci a toi.

EDIT:

Code:

$data = $request->getPost()->toArray(); 
$categ = new Categorie;
$hy = new DoctrineObject($this->getEntityManager());
$data['CatMesure'] = $this->getMesureRepository()->find($data['CatMesure']);
$categ = $hy->hydrate($data, $categ);

$em->persist($categ);
$em->flush();

j'aurai pensé que l'hydratation mes créer toute seul un objet Mesure, mais si je laisse la valeur de $data['catMesure'] (valeur poster) il me retourne une exception:
argument 1 passed to Catalogue\Entity\Categorie::setCatMesure() must be an instance of Catalogue\Entity\Mesure, string given, called in ...etc...

J'ai raté quelque chose ou c'est le fonctionnement normal?
sa marche bien avec
$data['CatMesure'] = $this->getMesureRepository()->find($data['CatMesure']);

Si je doit faire sa a chaque dépendance je vois plus trop l’intérêt, je pense donc que j'ai rater quelque chose ^^.
Je pense que c'est lié au faite que je sois en ajax, mais alors c'est pas plus mal car cela me permettra de mieux comprendre le processus d'hydratation plutôt que de laissé faire zend/Form :p

Je cherche encore mais je veut bien un chti coup de pousse...

EDIT 2:
Sa y'est trouver: erreur de majuscule dans les donné posté...dans le pré fixage  de mes champs, par habitude je met toujours la ou les 1er lettre de la table,pour simpliflier les jointure, avec dotrine je vois que non seulement c'est plus la pêne, mais sa induit en erreur >.< bon a savoir!

Dernière modification par Splyf (23-01-2014 20:43:55)

Hors ligne

 

#4 04-02-2014 14:33:29

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

Splyf a écrit:

j'aurai pensé que l'hydratation mes créer toute seul un objet Mesure, mais si je laisse la valeur de $data['catMesure'] (valeur poster) il me retourne une exception:
argument 1 passed to Catalogue\Entity\Categorie::setCatMesure() must be an instance of Catalogue\Entity\Mesure, string given, called in ...etc...

J'ai raté quelque chose ou c'est le fonctionnement normal?
sa marche bien avec
$data['CatMesure'] = $this->getMesureRepository()->find($data['CatMesure']);

Si je doit faire sa a chaque dépendance je vois plus trop l’intérêt, je pense donc que j'ai rater quelque chose ^^.

Bonjour, je me posais la même question, tu as trouvé la solution ou on doit récupérer l'enregistrement lié dans la BDD avant chaque ajout ?

Hors ligne

 

#5 04-02-2014 15:39:39

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

Re: méthode "populate" et association

Il faut respecter les noms des attributs lorsque l'on nomme son formulaire. Un fieldset est une représentation d'une entité sous forme d'un formulaire, il faut donc conserver cette logique pour que l'hydrateur puisse remplir correctement l'objet. Comment pourrait-il savoir que $['toto'] correspond à l'attribut $maman de ton objet ... Faut rester cohérent tout du long.
Pour les associations si le fieldset est correctement définie il y a normalement un composant de formulaire doctrine qui y est indiqué donc la requête est faite automatiquement au chargement du formulaire il n'y a pas besoin de la faire une seconde fois pour créer l'objet c'est tout l'intérêt du composant.

Hors ligne

 

#6 04-02-2014 16:26:54

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

J’avoue avoir du mal à comprendre. S'il me sort cette erreur, c'est qu'il a très bien pu associé les champs du fieldset aux attributs de l'entité non ? J'ai spécifié dans le select la propriété qu'il devait renseigner lorsque le champ est rempli (avec la clé property).
Lorsque je change les noms, il me soumet le formulaire sans prendre en compte ce qui est mis dans le select (pas d'erreur, mais le champ est null).

Qu'est ce qui doit s'appeler comme quoi ? Les champs du fieldset portent le même nom que les attributs de l'entité.

Hors ligne

 

#7 04-02-2014 16:43:39

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

Re: méthode "populate" et association

Faudrait que tu me donnes le code de ton formulaire, de tes entités et de ton contrôleur parce que comme ça je vois pas trop comment t'expliquer sad

Hors ligne

 

#8 04-02-2014 17:00:41

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

Code:

[lang=php]
//Mon controller (pas grand chose d'intéressant là dedans je pense)
$form = $this->getCategoryForm();
$form->bind($this->getCategory());
$entityManager = $this->getEntityManager();

if($this->getRequest()->isPost()) {
    $data = $this->getRequest()->getPost();
    $form->setData($data);
    
    if($form->isValid()) {
        $entityManager->persist($this->getCategory());
        $entityManager->flush();
    }
}

//Formulaire

public function __construct()
{
    parent::__construct('category');
}

public function init()
{
    $this->add(array(
        'type' => 'Namespace\Form\Fieldset\Category',
            'options' => array(
                 'use_as_base_fieldset' => true,
            ),
    ));
}

//Fieldset
public function __construct()
{
    parent::__construct('category');
}

public function init()
{
    $this->add(array(
        'type' => 'DoctrineModule\Form\Element\ObjectSelect',
        'options' => array(
            'label_generator' => function($entity){
                return $entity->getLabel();
            },
            'empty_option' => 'Sélectionnez un parent',
            'object_manager' => $this->getServiceLocator()->getServiceLocator()->get('entityManager'),
            'target_class' => 'Namespace\Model\Entity\SqCategory', //J'ai changé la config pour ne pas mélanger les entités des repositories
            'property' => 'parent',
            'is_method' => true,
        ),
        'name' => 'parent',
    ));
    
    $this->setHydrator(
        $this->getServiceLocator()
        ->getServiceLocator()->get('doctrineHydrator')
    )->setObject(
        $this->getServiceLocator()
        ->getServiceLocator()->get('category')
    );
}

//Mon entité
     /**
     * @var \Namespace\Model\Entity\SqCategory
     *
     * @ORM\ManyToOne(targetEntity="Namespace\Model\Entity\SqCategory")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     * })
     */
    private $_parent;

     /**
     * Set _parent
     *
     * @param \Namespace\Model\Entity\SqCategory $parent
     * @return SqCategory
     */
    public function setParent(\Namespace\Model\Entity\SqCategory $parent = null)
    {
        $this->_parent = $parent;

        return $this;
    }

Voilà mon code (j'ai essayé d'enlever tout le superflu)

Dernière modification par Seryus (05-02-2014 14:13:04)

Hors ligne

 

#9 04-02-2014 17:38:12

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

Re: méthode "populate" et association

Pourquoi un $this->getCategory() dans ton action ??? Ca fait quoi ? C'est juste un getter ou ça fait des choses en plus ? Parce que ça n'a pas de sens de l'avoir comme attribut de ton contrôleur?

Donnes un nom à ton fieldset dans le formulaire.

Alors ton histoire de modifier la config pour ne pas mélanger les entités des répository je vois pas ce que ça t'apporte, perso ça me perturbe plus qu'autre chose. Si tu respectes les conventions de nommage un repository a ce nom de classe : MonEntiteRepository et l'entité MonEntite. Donc à partir de là ... De plus tu les mets généralement dans le dossier Repository tandis que les entités dans Entity. Enfin bref pas bien grave. Tu peux importer le namespace aussi ça t'évitera les noms de classe à rallonge.

Tu aimes de compliquer la vie smile. Pour l'hydrateur :
$this->setHydrator(new DoctrineHydrator($this->getObjectManager(), 'Namespace\Model\Entity\SqCategory'))
            ->setObject(new SqCategory());

Pour injecter automatiquement l'object manager à ton formulaire tu dois ajouter l'interface ObjectManagerAwareInterface et ajouter l'initializer qui va bien dans la configuration du formElementManager

Ca devrait être mieux déjà. Ensuite les "_" dans le début du nom d'une variable pour dire qu'elle est privée je suis pas fan non plus wink !

Hors ligne

 

#10 04-02-2014 17:56:07

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

$this->getCategory() me renvoie l'entité SqCategory :

Code:

[lang=php]
public function getCategory()
{
    if(!$this->category) {
        $sl = $this->getServiceLocator();
        $this->category = $sl->get('category');
    }
    
    return $this->category;
}

Pour le reste, il me semblait qu'il valait mieux que les objets ne soient créés que dans le serviceLocator non ?

J'ai mis à jour DoctrineModule (la version de fin Janvier 2014) et le 2ème paramètre de DoctrineHydrator n'est plus nécessaire semble-t-il (en tout cas y'a plus d'erreur).

J'ai mis un nom à mon fieldset, mais ça n'a pas l'air de résoudre mon problème sad

Hors ligne

 

#11 04-02-2014 18:04:55

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

Re: méthode "populate" et association

Faudrait que tu me donnes le message exact d'erreur.

Oui c'est mieux m'enfin tu mets pas tout et n'importe quoi dedans ... Les modèles n'ont rien à y faire par exemple.

Ah peut être pourtant il me semble que je suis à jour et ça pose pas de problèmes. Donc là je ne sais pas te dire ^.

Hors ligne

 

#12 04-02-2014 18:08:39

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

C'est la même erreur que Splyf plus haut, en gros que je ne passe pas le bon type de paramètre à ma fonction setParent(), je lui passe (malgré moi) un objet de type string plutôt qu'un objet de type SqCategory.

Dernière modification par Seryus (04-02-2014 18:14:32)

Hors ligne

 

#13 05-02-2014 09:05:17

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

Re: méthode "populate" et association

Là comme ça je vois pas :s.

Hors ligne

 

#14 05-02-2014 09:48:14

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

Bon j'ai réussi à faire fonctionner en enlevant les "_" devant les attributs privés de mon entité (et dans les annotations). A priori le problème vient de là, aurais-tu une idée de comment le corriger autrement ? Une erreur de ma part dans les entités peut être  (je ne suis pas vraiment à l'aise avec ça) ?

Code:

[lang=php]
     /**
     * @var \Namespace\Model\Entity\SqCategory
     *
     * @ORM\ManyToOne(targetEntity="Namespace\Model\Entity\SqCategory")
     * @ORM\JoinColumns({
     *   @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
     * })
     */
    private $_parent;

     /**
     * Set _parent
     *
     * @param \Namespace\Model\Entity\SqCategory $parent
     * @return SqCategory
     */
    public function setParent(\Namespace\Model\Entity\SqCategory $parent = null)
    {
        $this->_parent = $parent;

        return $this;
    }

    /**
     * Get _parent
     *
     * @return \Namespace\Model\Entity\SqCategory 
     */
    public function getParent()
    {
        return $this->_parent;
    }

Hors ligne

 

#15 05-02-2014 10:42:23

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

Re: méthode "populate" et association

Orkin a écrit:

Il faut respecter les noms des attributs lorsque l'on nomme son formulaire. Un fieldset est une représentation d'une entité sous forme d'un formulaire, il faut donc conserver cette logique pour que l'hydrateur puisse remplir correctement l'objet. Comment pourrait-il savoir que $['toto'] correspond à l'attribut $maman de ton objet ... Faut rester cohérent tout du long.

Orkin a écrit:

Ensuite les "_" dans le début du nom d'une variable pour dire qu'elle est privée je suis pas fan non plus wink !

Hors ligne

 

#16 05-02-2014 10:58:43

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

On ne peut donc pas garder les "_" devant les noms des variables ?

Hors ligne

 

#17 05-02-2014 11:51:11

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

Re: méthode "populate" et association

Faut croire que non, et ça ne sert à rien.

Hors ligne

 

#18 05-02-2014 11:56:34

Seryus
Membre
Date d'inscription: 17-02-2012
Messages: 128

Re: méthode "populate" et association

Bon tant pis, je les enlève !

Merci pour ton aide smile

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