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

Symfony PHP Discussion :

[Form] Relation many-to-many


Sujet :

Symfony PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de Furlaz
    Homme Profil pro
    Responsable Qualité
    Inscrit en
    Mai 2006
    Messages
    210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable Qualité
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 210
    Par défaut [Form] Relation many-to-many
    Bonjour à tous,

    J'ai un problème pour persister correctement mes informations en BDD avec Doctrine.
    Voici le contexte. Tout d'abord, j'ai 2 classes :
    • Profil
    • Utilisateur


    Ma 1ère classe est assez simple :
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    namespace Projet\**Bundle\Entity;
     
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
     
    /**
     * Profil
     *
     * @ORM\Table()
     * @ORM\Entity(repositoryClass="Projet\**Bundle\Entity\ProfilRepository")
     */
    class Profil
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
     
        /**
         * @var string
         *
         * @Assert\MinLength(
         * 		limit=2,
         * 		message="Le nom du projet doit faire au minimum 2 caractères"
         * )
         * @Assert\MaxLength(
         * 		limit=15,
         * 		message="Le nom du projet doit faire au maximum 15 caractères"
         * )
         * 
         * @ORM\Column(name="nom", type="string", length=15)
         */
        private $nom;
     
     
        /**
         * Get id
         *
         * @return integer 
         */
        public function getId()
        {
            return $this->id;
        }
     
        /**
         * Set nom
         *
         * @param string $nom
         * @return Profil
         */
        public function setNom($nom)
        {
            $this->nom = $nom;
     
            return $this;
        }
     
        /**
         * Get nom
         *
         * @return string 
         */
        public function getNom()
        {
            return $this->nom;
        }
    }
    Et ma 2ème classe avec la relation ManytoMany :
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    <?php
     
    namespace Projet\**Bundle\Entity;
     
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
     
    /**
     * Utilisateur
     *
     * @ORM\Table()
     * @ORM\Entity(repositoryClass="Projet\**Bundle\Entity\UtilisateurRepository")
     */
    class Utilisateur
    {
        /**
         * @var integer
         *
         * @ORM\Column(name="id", type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
     
        /**
         * @var string
         *
         * @Assert\MinLength(
         * 		limit=2,
         * 		message="Le prénom doit faire au minimum 2 caractères"
         * )
         * @Assert\MaxLength(
         * 		limit=30,
         * 		message="Le prénom doit faire au maximum 30 caractères"
         * )
         * 
         * @ORM\Column(name="prenom", type="string", length=30)
         */
        private $prenom;
     
        /**
         * @var string
         * 
         * @Assert\MinLength(
         * 		limit=2,
         * 		message="Le nom doit faire au minimum 2 caractères"
         * )
         * @Assert\MaxLength(
         * 		limit=30,
         * 		message="Le nom doit faire au maximum 30 caractères"
         * )
         *
         * @ORM\Column(name="nom", type="string", length=30)
         */
        private $nom;
     
        /**
    	* @ORM\ManyToMany(targetEntity="Projet\**Bundle\Entity\Profil", cascade={"persist"})
    	*/
        private $profil;
     
        /**
         * @var string
         * 
         * @Assert\Email(
         * 		message="L'adresse email indiquée n'est pas valide"
         * )
         * @Assert\MaxLength(
         * 		limit=70,
         * 		message="L'adresse email doit faire au maximum 70 caractères"
         * )
         * 
         * @ORM\Column(name="email", type="string", length=70)
         */
        private $email;
     
        /**
         * @var string
         * 
         * @Assert\Regex(
         * 		pattern="/^0[1-68]([-. ]?\d{2}){4}$/", 
         * 		message="Le numéro de téléphone indiqué n'est pas valide"
         * )
         * 
         * @ORM\Column(name="telephone", type="string", length=15, nullable=true)
         */
        private $telephone;
     
        /**
         * @var \DateTime
         * 
         * @Assert\DateTime
         * 
         * @ORM\Column(name="date_inscription", type="datetime")
         */
        private $date_inscription;
     
        /**
         * @var string
         *
         * @ORM\Column(name="droits", type="string", length=20, nullable=true)
         */
        private $droits;
     
    	public function __construct()
    	{
    		$this->date_inscription = new \Datetime;
    		$this->profil = new \Doctrine\Common\Collections\ArrayCollection();
    	}
     
    	public function __toString()
    	{
    		return $this->prenom . ' ' . $this->nom;
    	}
     
        /**
         * Get id
         *
         * @return integer 
         */
        public function getId()
        {
            return $this->id;
        }
     
        /**
         * Set prenom
         *
         * @param string $prenom
         * @return Utilisateur
         */
        public function setPrenom($prenom)
        {
            $this->prenom = $prenom;
     
            return $this;
        }
     
        /**
         * Get prenom
         *
         * @return string 
         */
        public function getPrenom()
        {
            return $this->prenom;
        }
     
        /**
         * Set nom
         *
         * @param string $nom
         * @return Utilisateur
         */
        public function setNom($nom)
        {
            $this->nom = $nom;
     
            return $this;
        }
     
        /**
         * Get nom
         *
         * @return string 
         */
        public function getNom()
        {
            return $this->nom;
        }
     
        /**
         * Set email
         *
         * @param string $email
         * @return Utilisateur
         */
        public function setEmail($email)
        {
            $this->email = $email;
     
            return $this;
        }
     
        /**
         * Get email
         *
         * @return string 
         */
        public function getEmail()
        {
            return $this->email;
        }
     
        /**
         * Set telephone
         *
         * @param string $telephone
         * @return Utilisateur
         */
        public function setTelephone($telephone)
        {
            $this->telephone = $telephone;
     
            return $this;
        }
     
        /**
         * Get telephone
         *
         * @return string 
         */
        public function getTelephone()
        {
            return $this->telephone;
        }
     
        /**
         * Set date_inscription
         *
         * @param \DateTime $dateInscription
         * @return Utilisateur
         */
        public function setDateInscription($dateInscription)
        {
            $this->date_inscription = $dateInscription;
     
            return $this;
        }
     
        /**
         * Get date_inscription
         *
         * @return \DateTime 
         */
        public function getDateInscription()
        {
            return $this->date_inscription;
        }
     
        /**
         * Set droits
         *
         * @param string $droits
         * @return Utilisateur
         */
        public function setDroits($droits)
        {
            $this->droits = $droits;
     
            return $this;
        }
     
        /**
         * Get droits
         *
         * @return string 
         */
        public function getDroits()
        {
            return $this->droits;
        }
     
        /**
         * Add profil
         *
         * @param \Projet\**Bundle\Entity\Profil $profil
         */
        public function addProfil(\Projet\**Bundle\Entity\Profil $profil)
        {
            $this->profil[] = $profil;
     
            return $this;
        }
     
        /**
         * Remove profil
         *
         * @param \Projet\**Bundle\Entity\Profil $profil
         */
        public function removeProfil(\Projet\**Bundle\Entity\Profil $profil)
        {
            $this->profil->removeElement($profil);
        }
     
        /**
         * Get profil
         *
         * @return \Doctrine\Common\Collections\Collection 
         */
        public function getProfil()
        {
            return $this->profil;
        }
    }
    L'objectif est de pouvoir créer un nouvel utilisateur avec un ou plusieurs profils. J'ai donc créé 2 classes pour la gestion de mon formulaire "Utilisateur" :
    • UtilisateurType
    • UtilisateurHandler


    Le 1ère me permet de créer le "modèle" de mon formulaire :
    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
    <?php
     
    namespace Projet\**Bundle\Form;
     
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolverInterface;
     
    class UtilisateurType extends AbstractType
    {
    	private $profils = 		array(	'Client' 		=> 'Client', 
    									'Développeur' 	=> 'Développeur', 
    									'Support' 		=> 'Support',
    									'Qualité' 		=> 'Qualité',
    									'Direction' 	=> 'Direction',
    									'Visiteur' 		=> 'Visiteur');
    	private $droits = 		array(	'Administrateur'=> 'Administrateur');
     
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->	add('prenom', 'text')
    			->	add('nom', 'text')
    			->	add('profil', 'entity', array(	'class'		=>	'QualiteoOutilBundle:Profil',
    												'property'	=>	'nom',
    												'expanded'	=>	false, 
    												'multiple'	=>	true))
    			->	add('droits', 'choice', array(	'choices'	=> 	$this->droits, 
    												'expanded'	=>	true, 
    												'multiple'	=>	true,
    												'required'  =>	false))
    			->	add('email', 'text')
    			->	add('telephone', 'text', array(	'required'  =>	false))
    			->	add('date_inscription', 'date', array(	'input'		=>	'datetime',
    														'widget'	=>	'single_text',
    														'read_only'	=>	true));
        }
     
        public function setDefaultOptions(OptionsResolverInterface $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'Projet\**Bundle\Entity\Utilisateur'
            ));
        }
     
        public function getName()
        {
            return 'projet_**bundle_utilisateurtype';
        }
    }
    Tandis que le 2ème se charge de persister en BDD (normalement), le tout :
    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
    <?php
     
    namespace Projet\**Bundle\Form;
     
    use Symfony\Component\Form\Form;
    use Symfony\Component\Form\FormHandler;
    use Symfony\Component\HttpFoundation\Request;
    use Doctrine\ORM\EntityManager;
    use Projet\**Bundle\Entity\Utilisateur;
    use Projet\**Bundle\Form\UtilisateurType;
    use Projet\**Bundle\Entity\Profil;
    use Projet\**Bundle\Form\ProfilType;
    use Symfony\Component\Form\AbstractType;
     
    class UtilisateurHandler extends FormHandler
    {
        public function process()
        {
    		if ($this->request->getMethod() == 'POST') {			
    			// On fait le lien entre la requête et le formulaire
    			$this->form->bindRequest($this->request);
     
    			// On vérifie la validité des informations rempli dans le formulaire
    			if ($this->form->isValid()) {
    				// On enregistre en base les valeurs correspondantes
    				$this->onSuccess($this->form->getData());
    				return true;
    			}
     
    			return false;
    		}
        }
     
        public function onSuccess(Utilisateur $utilisateur)
        {
    		$this->em->persist($utilisateur);
    		echo 'Post Persist Utilisateur';
    		$this->em->flush();
    		echo 'Post Flush';
        }
    }
    Le problème c'est que la persistance ne fonctionne pas. Il n'a pas l'air d'aimer la relation entre la classe Utilisateur et la classe Profil.
    J'ai le message d'erreur suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Notice: Array to string conversion in /var/www/Projet/vendor/doctrine/dbal/lib/Doctrine/DBAL/Statement.php line 103
    Une idée de mon problème ? J'ai beau chercher depuis quelques jours, je ne trouve rien qui puisse m'aider !

    Merci par avance... :-)

  2. #2
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Salut, que donne le dump de this->request avant qu'il soit bindé ?

  3. #3
    Membre confirmé Avatar de Furlaz
    Homme Profil pro
    Responsable Qualité
    Inscrit en
    Mai 2006
    Messages
    210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable Qualité
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 210
    Par défaut
    Salut Nico,

    Salut, que donne le dump de this->request avant qu'il soit bindé ?
    Qu'entends-tu par là ? Savoir si le $this->request fonctionne correctement ?
    J'ai essayé de mettre des echo un peu partout et tout fonctionne jusqu'au isvalid()... Et c'est ensuite, pour faire le persist() que ça ne fonctionne plus :-(

  4. #4
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Je voudrais voir le contenu de ce que tu postes. Si le bind et la validation passent il faut juste que tu saches ce qui est passé à ton onSuccess.

    Place cette ligne au début de ta méthode onSuccess et montre le contenu de ton objet.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    \Doctrine\Common\Util\Debug::dump($utilisateur);die;
    Note celà dit que l'erreur qui t'es retournée est une erreur au niveau du bind me semble-t-il.

  5. #5
    Membre confirmé Avatar de Furlaz
    Homme Profil pro
    Responsable Qualité
    Inscrit en
    Mai 2006
    Messages
    210
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Responsable Qualité
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2006
    Messages : 210
    Par défaut
    Merci Nico pour cette astuce que je ne connaissais pas.

    Voilà le résultat qu'il me sort :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    object(stdClass)#442 (9) { ["__CLASS__"]=> string(39) "Projet\**Bundle\Entity\Utilisateur" ["id"]=> NULL 
    ["prenom"]=> string(6) "Michel" 
    ["nom"]=> string(4) "Test" 
    ["profil"]=> array(2) { [0]=> string(34) "Projet\**Bundle\Entity\Profil" [1]=> string(34) "Projet\**Bundle\Entity\Profil" } 
    ["email"]=> string(13) "test@toto.com" 
    ["telephone"]=> NULL
    ["date_inscription"]=> object(stdClass)#488 (3) { ["__CLASS__"]=> string(8) "DateTime" 
    ["date"]=> string(25) "2013-03-01T00:00:00+01:00" ["timezone"]=> string(12) "Europe/Paris" }
    ["droits"]=> array(0) { } }
    Il semble bien y avoir quelque chose dans mon champ "profil"...

    EDIT : Remarque, en y regardant de plus près, il ne m'enregistre pas tellement ce qu'il faut dans "profil". Il me dit juste que c'est des classes Profil mais ça ne dit pas exactement quelle instance... Je vois pas trop quoi changer du coup !

  6. #6
    Membre Expert Avatar de Nico_F
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2011
    Messages
    728
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Avril 2011
    Messages : 728
    Par défaut
    Félicitation Madame : c'est un string !

    En gros il faut que tu vois pourquoi tu n'as pas d'objets dans ta collection de profil mais uniquement des strings. Ça peut être dû à pas mal de choses que j'ai mis de coté jusqu'à présent mais pour faire le tour de ce que j'ai vu dans ton code je te laisse faire un tour d'horizon :

    • L'entité Profil n'est mappé à aucune table.
    • L'annotation ManyToMany n'est présente que d'un coté : il faudrait rajouter un attribut $utilisateurs avec l'annotation inverse
    • Il serait judicieux d'utiliser l'annotation verbeuse précisant la table intermédiaire pour être sur que la liaison se fasse
    • Si effectivement il s'agit bien d'une relation ManyToMany, mettre un s à $profils permettrait d'éviter toute confusion

Discussions similaires

  1. PGSQL-EclipseLink Relation One To Many et Many To One
    Par faitor1 dans le forum Persistance des données
    Réponses: 0
    Dernier message: 30/01/2015, 19h46
  2. [2.x] Embed form avec relation one to many
    Par dyron dans le forum Symfony
    Réponses: 8
    Dernier message: 24/07/2014, 09h07
  3. relation many-to-many avec forms
    Par m_elkhaldi01 dans le forum Forms
    Réponses: 2
    Dernier message: 27/10/2011, 18h19
  4. [AC-2010] Form with Subform dans le cadre d'une relation Many-to-Many
    Par NooBxL dans le forum IHM
    Réponses: 1
    Dernier message: 19/05/2011, 21h57
  5. Un peu de mal a comprendre le concepte "one-to-many" et "many-to-many"
    Par chriscoolletoubibe dans le forum Hibernate
    Réponses: 4
    Dernier message: 29/03/2007, 18h50

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