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 :

Enregistrer une collection imbriquée dans une autre collection


Sujet :

Symfony PHP

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2019
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Calvados (Basse Normandie)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Mars 2019
    Messages : 3
    Par défaut Enregistrer une collection imbriquée dans une autre collection
    Voila je rencontre un petit problème avec mon code.

    J'ai un formulaire de prestataires dans lequel je souhaite intégrer une collection de prestations et pour chaque prestation y intégrer une collection de expériences.
    J'ai donc un formulaire avec un ArrayColllection qui lui contient un autre ArrayCollection.

    J'ai donc créé les entités Prestataire, Prestation et Expérience :

    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
     
    <?php
    namespace App\Entity;
     
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    use Doctrine\ORM\Mapping as ORM;
     
    /**
     * @ORM\Entity(repositoryClass="App\Repository\PrestataireRepository")
     */
    class Prestataire
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
     
        /**
         * @ORM\Column(type="string", length=255, nullable=true)
         */
        private $name;
     
        /**
         * @ORM\OneToMany(targetEntity="App\Entity\Prestation", mappedBy="prestataire", cascade={"persist"}, orphanRemoval=true)
         */
        private $prestations;
     
        public function __construct()
        {
            $this->caterings = new ArrayCollection();
        }
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getName(): ?string
        {
            return $this->name;
        }
     
        public function setName(?string $name): self
        {
            $this->name = $name;
            return $this;
        }
     
        /**
         * @return Collection|Prestation[]
         */
        public function getPrestations(): Collection
        {
            return $this->prestations;
        }
     
        public function addPrestation(Prestation $prestation): self
        {
            if (!$this->prestations->contains($prestation)) {
                $this->prestations[] = $prestation;
                $prestation->setPrestataire($this);
            }
            return $this;
        }
     
        public function removePrestation(Prestation $prestation): self
        {
            if ($this->prestations->contains($prestation)) {
                $this->prestations->removeElement($prestation);
                // set the owning side to null (unless already changed)
                if ($prestation->getPrestataire() === $this) {
                    $prestation->setPrestataire(null);
                }
            }
            return $this;
        }
    }
    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
     
    <?php
    namespace App\Entity;
     
    use Doctrine\Common\Collections\ArrayCollection;
    use Doctrine\Common\Collections\Collection;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
     
    /**
     * @ORM\Entity(repositoryClass="App\Repository\PrestationRepository")
     */
    class Prestation
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
     
        /**
         * @ORM\Column(type="text", nullable=true)
         */
        private $descriptif;
     
        /**
         * @ORM\ManyToOne(targetEntity="App\Entity\Prestataire", inversedBy="prestations")
         */
        private $prestataire;
     
        /**
         * @ORM\OneToMany(targetEntity="App\Entity\Experience", mappedBy="prestation", cascade={"persist"}, orphanRemoval=true)
         */
        private $experiences;
     
        public function __construct()
        {
            $this->experiences = new ArrayCollection();
        }
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getDescriptif(): ?string
        {
            return $this->descriptif;
        }
     
        public function setDescriptif(?string $descriptif): self
        {
            $this->descriptif = $descriptif;
            return $this;
        }
     
        public function getPrestataire(): ?Prestataire
        {
            return $this->prestataire;
        }
     
        public function setPrestataireLogistique(?Prestataire $prestataire): self
        {
            $this->prestataire = $prestataire;
     
            return $this;
        }
     
        /**
         * @return Collection|Experience[]
         */
        public function getExperiences(): Collection
        {
            return $this->experiences;
        }
     
        public function addExperience(Experience $experience): self
        {
            if (!$this->experiences->contains($experience)) {
                $this->experiences[] = $experience;
                $experience->setPrestation($this);
            }
            return $this;
        }
     
        public function removeExperience(Experience $experience): self
        {
            if ($this->experiences->contains($experience)) {
                $this->experiences->removeElement($experience);
                // set the owning side to null (unless already changed)
                if ($experience->getPrestation() === $this) {
                    $experience->setPrestation(null);
                }
            }
            return $this;
        } 
    }
    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
     
    <?php
    namespace App\Entity;
     
    use Doctrine\ORM\Mapping as ORM;
     
    /**
     * @ORM\Entity(repositoryClass="App\Repository\ExperienceRepository")
     */
    class Experience
    {
        /**
         * @ORM\Id()
         * @ORM\GeneratedValue()
         * @ORM\Column(type="integer")
         */
        private $id;
     
        /**
         * @ORM\Column(type="string", length=255, nullable=true)
         */
        private $titre;
     
        /**
         * @ORM\ManyToOne(targetEntity="App\Entity\Prestation", inversedBy="experiences")
         * @ORM\JoinColumn(nullable=false)
         */
        private $prestation;
     
        public function getId(): ?int
        {
            return $this->id;
        }
     
        public function getTitre(): ?string
        {
            return $this->titre;
        }
     
        public function setTitre(?string $titre): self
        {
            $this->titre = $titre;
            return $this;
        }
     
        public function getPrestation(): ?Prestation
        {
            return $this->prestation;
        }
     
        public function setPrestation(?Prestation $prestation): self
        {
            $this->prestation = $prestation;
            return $this;
        }
    }
    Voici les Forms correspondants à ces entités

    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
     
    <?php
    namespace App\Form;
     
    use App\Entity\Prestataire;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\CollectionType;
    use Symfony\Component\Form\Extension\Core\Type\SubmitType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
     
    class PrestataireType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('prestations', CollectionType::class, [
                    'entry_type' => PrestationType::class,
                    'entry_options' => [
                        'label' => false,
                    ],
                    'allow_add' => true,
                    'allow_delete' => true,
                    'required' => false,
                    'by_reference' => false,
                    'prototype' => true,
                    'prototype_name' => 'prestation'
                ])
                ->add('save', SubmitType::class, [
                    'attr' => [
                        'class' => 'btn btn-primary',
                    ]
                ])
            ;
        }
     
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Prestataire::class,
            ]);
        }
    }
    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
     
    <?php
    namespace App\Form;
     
    use App\Entity\Catering;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\CollectionType;
    use Symfony\Component\Form\Extension\Core\Type\TextareaType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
     
    class PrestationType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('descriptif', TextareaType::class, [
                    'label' => " Descriptif de l’activité et du service proposé",
                ])
                ->add('experiences', CollectionType::class, [
                    'entry_type' => ExperienceType::class,
                    'entry_options' => [
                        'label' => false,
                    ],
                    'allow_add' => true,
                    'allow_delete' => true,
                    'required' => false,
                    'by_reference' => true,
                    'prototype' => true,
                ])
            ;
        }
     
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Prestation::class,
            ]);
        }
    }
    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
     
    <?php
    namespace App\Form;
     
    use App\Entity\Travaux;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\Extension\Core\Type\TextType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
     
    class TravauxType extends AbstractType
    {
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder
                ->add('titre', TextType::class, [
                    'label' => false,
                ])
            ;
        }
     
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults([
                'data_class' => Experience::class,
            ]);
        }
    }
    Et voici la fonction de mon controller

    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
     
    /**
    * @Route("/prestataire/new", name="prestataire_create")
    * @Route("/prestataire/edit", name="prestataire_edit")
    */
    public function editionform(PrestataireRepository $repository, Request $request, ObjectManager $manager)
        {
            $user = $this->getUser();
     
            $prestataire = $repository->findOneByUser($user);
     
            if(!$prestataire){
                $prestataire = new Prestataire();
            }
     
            $form = $this->createForm(PrestataireType::class, $prestataire);
            $form->handleRequest($request);
     
            if($form->isSubmitted() && $form->isValid()){
            	//Je boucle l'ArrayCollection de Prestation
                foreach($prestataire->getPrestations() as $prestation){
                	$prestation->setPrestataire($prestation);
                    $manager->persist($prestation);
                    //Je flush le $manager afin d'obtenir l'id  de la Prestation
                    $manager->flush();
     
                    foreach ($prestation->getExperience() as $experience){
                    	$experience->setPrestation($prestation);
    					$manager->persist($experience);
                    }
     
                     //Enfin je flush de nouveau le $manager d'enregistrer les expériences
                	$manager->flush();   
               }
     
                return $this->redirectToRoute('dashboard_user');
            }
     
            return $this->render('recensement/prestataire.html.twig', [
                'form' => $form->createView(),
            ]);
        }
    Je voudrais que pour chaque prestation, l'ensemble des expériences soit enregistré.
    Mais hélas voilà ce que j'obtiens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Could not determine access type for property "experiences" in class "App\Entity\Prestation": Neither the property "experiences" nor one of the methods "addExperienceson()"/"removeExperienceson()", "addExperiencesum()"/"removeExperiencesum()", "setExperiences()", "experiences()", "__set()" or "__call()" exist and have public access in class "App\Entity\Prestation".
    C'est comme si le controller recherchait les fonctions getExperiences , addExperience et removeExperience dans l'entité Prestataire alors que celles-ci se trouvent dans mon entité Prestation puisque les expériences sont une collection de la collection Prestation.

    Je tente depuis plusieurs de trouver une solution mais toute mes recherches sont infructueuses donc si quelqu'un peut me donner une solution ça sera avec un immense plaisir.

    Merci

  2. #2
    Modérateur

    Avatar de MaitrePylos
    Homme Profil pro
    DBA
    Inscrit en
    Juin 2005
    Messages
    5 502
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : DBA
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 502
    Par défaut
    Bonjour,

    D'où viens caterings ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     public function __construct()
        {
            $this->caterings = new ArrayCollection();
        }

Discussions similaires

  1. Réponses: 3
    Dernier message: 30/11/2018, 15h48
  2. [OpenOffice][Base de données] Liste de choix, enregistrer une autre valeur en suplément.
    Par JaqLau dans le forum OpenOffice & LibreOffice
    Réponses: 1
    Dernier message: 31/01/2018, 13h18
  3. Réponses: 2
    Dernier message: 18/03/2008, 14h54
  4. Comment centrer mon div imbriquer dans un autre
    Par pierrot10 dans le forum Mise en page CSS
    Réponses: 3
    Dernier message: 03/12/2006, 13h15
  5. Réponses: 5
    Dernier message: 02/10/2006, 13h39

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