Partage
  • Partager sur Facebook
  • Partager sur Twitter

Symfony Probleme d'édition d'un objet

Probleme sur le flush en BDD

    14 juin 2024 à 17:00:00

    Bonjour, je fais une nouvelle fois appel à votre science :D :

    Je réalise une annuaire reférençant des professionnel sous Symfony 7.

    J'ai une classe "Professionnel" ratachée à une table en BDD du même nom. Lors de la création d'un professionnel je peux lui ajouter un ou plusieurs métiers rattachés à une autre table "Metier" en Many to Many, jusque là aucun problème. Par contre lors de l'édition d'un professionnel déjà existant, la modification / ajout / suppression d'un / des métiers à ce professionel est impossible, ma table reste dans le même état qu'avant l'édition.

    Je précise que je n'ai aucun message d'erreur et que les autres champs de mon Professionnel sont bien modifiés correctement. L'objet également est bon si je fait un dump de mon formulaire j'obtiens bien mes modifications. Mais au moment du flush en BDD il y a quelque chose qui coince.

    Please help. Merci d'avance.

    #[Route('/edit-pro-{id_pro}', name: 'edit-pro')]
        public function editPro($id_pro, Request $request, EntityManagerInterface $em, ProfessionnelRepository $professionnelRepository, InterventionRepository $interventionRepository){
            
            $pro = $professionnelRepository->findOneBy([
                'id' => $id_pro
            ]);
    
            $interventions = $interventionRepository->findBy([
                'professionnel' => $pro
            ]);
    
            if(!$pro){
                throw $this->createNotFoundException("Le professionnel demandé n'existe pas...");
            }
    
            $form = $this->createForm(ProFormType::class, $pro);
            $form->handleRequest($request);
            
            if($form->isSubmitted() && $form->isValid()){
                $data = $form->getData();   
                $em->persist($data);
                $em->flush();
                $this->addFlash('success', 'Vos modifications ont bien été prises en compte !');
            }
    
            $formView = $form->createView();
            return $this->render('admin/edit-pro.html.twig', [
                'pro' => $pro,
                'formView' => $formView,
                'interventions' => $interventions
            ]);
        }



    • Partager sur Facebook
    • Partager sur Twitter
      14 juin 2024 à 23:41:13

      Salut

      Je voudrais voir les mappings entre Professionel et Metier, s'il te plaît. Des deux côtés, et uniquement ces mappings avec les méthodes, pas l'entier des deux entités, merci d'avance.

      -
      Edité par Ymox 16 juin 2024 à 1:23:45

      • Partager sur Facebook
      • Partager sur Twitter
        16 juin 2024 à 15:08:40

        Salut Ymox et merci de ton retour. Voici un extrait des 2 classes, est-ce bien ce que tu attends ? Merci.

        Pour la classe Professionnel :

         #[ORM\ManyToMany(targetEntity: Metier::class, mappedBy: 'professionnel')]
            private Collection $metiers; 

        public function __construct()
            {
                $this->metiers = new ArrayCollection();
            }
             
        /**
             * @return Collection<int, Metier>
             */
            public function getMetiers(): Collection
            {
                return $this->metiers;
            }
        
            public function addMetier(Metier $metier): static
            {
                if (!$this->metiers->contains($metier)) {
                    $this->metiers->add($metier);
                    $metier->addProfessionnel($this);
                }
        
                return $this;
            }
        
            public function removeMetier(Metier $metier): static
            {
                if ($this->metiers->removeElement($metier)) {
                    $metier->removeProfessionnel($this);
                }
        
                return $this;
            }

        Pour la Classe Metier :

         #[ORM\ManyToMany(targetEntity: Professionnel::class, inversedBy: 'metiers')]
            private Collection $professionnel;
        public function __construct()
            {
                $this->professionnel = new ArrayCollection();
            }
            /**
             * @return Collection<int, Professionnel>
             */
            public function getProfessionnel(): Collection
            {
                return $this->professionnel;
            }
        
            public function addProfessionnel(Professionnel $professionnel): static
            {
                if (!$this->professionnel->contains($professionnel)) {
                    $this->professionnel->add($professionnel);
                }
        
                return $this;
            }
        
            public function removeProfessionnel(Professionnel $professionnel): static
            {
                $this->professionnel->removeElement($professionnel);
        
                return $this;
            }
         






        • Partager sur Facebook
        • Partager sur Twitter
          16 juin 2024 à 21:05:05

          Alors je m'en doutais un peu, même si j'ai toujours de la peine à l'expliquer. Il y a deux points qui sont à considérer.

          1. Les ManyToMany ont, comme toutes les relations, un côté qui "possède" la relation (owning side) et un autre qui est "l'inverse" (inverse side) — et c'est totalement indépendant du fait que la relation soit ou non bi-directionnelle. Or, pour ce qui est des ManyToMany, c'est plus une conception métier qui doit entrer en ligne de compte.
            Si tu modifies un objet Professionnel et que tu lui adjoins un Métier, c'est que, de par cette logique d'utilisation, Professionnel est la classe qui possède la relation. Mais, d'après les mappings montrés, la relation est "dans l'autre sens de possession" : il faudrait avoir inversedBy dans Professionel et mappedBy dans Métier. Tout ça parce que Doctrine ne vérifie que la partie qui possède la relation en cas de cascade d'opérations.
            Une bonne manière de se rendre compte de qui "possède" la relation est de se demander dans quel sens conserver la relation s'il fallait absolument conserver une relation unidirectionnelle.
            Concrètement, il faut donc modifier ces deux parties des mappings, mais en plus supprimer les méthodes Professionnel::addMétier et Métier::addProfessionnel pour les re-générer afin qu'elles contiennent les bonnes logiques de fonctionnement. Il pourrait être possible de faire les modifications de ces deux méthodes à la main, mais il faut être certain de ce qui est fait.
            Voir à ce propos la FAQ Symfony 2 et un article à ce sujet dans les SymfonyCasts.
          2. Justement, il n'y a aucun comportement de cascade de précisé dans ces mappings. Ne faire que l'étape précédente ne changerait à mon sens pas le problème, et ne réaliser que cette étape 2 causerait d'autres soucis. En tout cas, il faut ajouter cascade: ["persist"] dans les mappings de Professionnel#métiers. Doctrine saura ainsi quoi faire des entités dans la collection, et ce à la mise à jour aussi.
          • Partager sur Facebook
          • Partager sur Twitter
            17 juin 2024 à 9:58:05

            Parfait, tu es un king !!

            J'ai du coup supprimé tout ce qui été en rapport avec Professionnel et Metier dans mes 2 entités et ai recréé "Metier" en ligne de commande à partir de Professionnel. Du coup j'ai bien inversedBydans Professionel et mappedBy dans Métier. J'ai également ajouter Dans Professionnel le fameux cascade: ["persist"] :

            #[ORM\ManyToMany(targetEntity: Metier::class, inversedBy: 'professionnels', cascade: ["persist"])]
                private Collection $Metier;


            Encore merci Ymox, avec tout ce que tu me dépannes je vais t'être redevable, Si tu passes près de Romans-sur-Isère fais moi signe ;-).

            -
            Edité par Jean-DavidIrles 17 juin 2024 à 9:59:33

            • Partager sur Facebook
            • Partager sur Twitter

            Symfony Probleme d'édition d'un objet

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            • Editeur
            • Markdown