Partage
  • Partager sur Facebook
  • Partager sur Twitter

Symfony 4 ManyToMany Query et Repository

Sujet résolu
    17 juillet 2019 à 15:09:31

    Bonjour, 

    J'ai deux entités liées (Montant et Demande)par une relation ManyToMany. En suivant quelques tuto sur le net, je suis parvenu à des pages qui pour un montant donné renvoie la liste des demandes associées et inversement. Mais quand j'essaie de faire la même chose au travers de listes déroulante : une liste déroulante de demande lance une méthode AJAX qui renvoie les montants associés, je ne trouve pas comment faire.. J'ai tenté de faire une requête personnalisée dans le fichier repository mais c'est comme si il ne me le prenait pas en compte et ne trouve pas la fonction et donc ma requête. 

    Voici le code : 

    Mes entités 

    /**
     *@ORM\Entity
     *@ORM\Table(name="demandederog")
     */
    class DemandeDerog
    {
        /**
        *@var int
        *
        *@ORM\Id
        *@ORM\GeneratedValue(strategy="AUTO")
        *@ORM\Column(type="integer")
        */
        private $id;
    
       /**
         *@ORM\ManyToMany(targetEntity="MontantDerog", mappedBy="demandes")
         */
        private $montants;
        ....
    } 
    
    /**
     *@ORM\Entity
     *@ORM\Table(name="montantderog")
     */
    class MontantDerog
    {
        /**
        *@var int
        *
        *@ORM\Id
        *@ORM\GeneratedValue(strategy="AUTO")
        *@ORM\Column(type="integer")
        */
        private $id;
    
        /**
         *@var DemandeDerog
         *
         *@ORM\ManyToMany(targetEntity="DemandeDerog", inversedBy="montants")
         *@ORM\JoinTable(
         *  name="demandemontantderog",  
         * )
         */
        private $demandes;
       ....
    }

    Ma vue twig et la requête AJAX : 

    .... 
    <div class="col-sm-6">
       {{ form_row(form.demande, {
           'attr': {'class': 'form-inline'},
            'label': 'Demande'
            })
        }}
    </div>
    
    $(document).ready(function() {
        idDemande = 1;
    
        $('#derogation_demande').on('change', function() {
            var idDemande = this.value; 
           // montant.empty();
            $.ajax({
                type: "POST",
                url: "{{ path('montant_ajax') }}",
                dataType: "json",
                data: {id: idDemande},
                success: function(data) {
                    var jsonData = JSON.parse(data);   
                    for(var i=0; i<jsonData.length; i++) {
                        montant.append('<option value="' + jsonData[i].id + '">' + jsonData[i].libelle + '</option>');
                    }
                }
            }); 
        });
    
    
    
    });

    La fonction appelée par AJAX : 

    /**
         *@Route("montant/ajax", name="montant_ajax")
         */
        public function ajaxMontant(Request $request)
        {
             if($request->isXmlHttpRequest()) {
                    $idDemande = $request->request->get('idDemande');          
    
                    $montants = $this->getDoctrine()
                            ->getRepository(Montantderog::class)
                            ->findByDemande($idDemande);
                    //dump($searchAdh);die();
                    if($searchForm){
                        $encoders = array(new XmlEncoder(), new JsonEncoder());
                        $normalizers = array(new ObjectNormalizer());
    
                        $serializer = new Serializer($normalizers, $encoders);
    
                        $jsonContent = $serializer->serialize($searchForm, 'json',[
                            'circular_reference_handler'=> function($object){
                                return $object->getId();
                            }
                        ]);
                        
                        $response = new JsonResponse();
                        $response->headers->set('Content-Type', 'application/json');
                        $response->setData(array($jsonContent));
    
                        return $response;
                    } else {
                        $response = new JsonResponse(["res" => "Pas d'adhérent correspondant."]);
    
                        return $response;
                    }
                }
        }

    Et enfin mon repository : 

    namespace App\Repository;
    
    use App\Entity\MontantDerog;
    
    use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
    use Symfony\Bridge\Doctrine\RegistryInterface;
    
    class MontantDerogRepository extends ServiceEntityRepository
    {
        public function __construct(RegistryInterface $registry)
        {
            parent::__construct($registry, MontantDerog::class);
        }
    
        public function findByDemande($idDemande): array
        {
        	$qb = $this->createQueryBuilder('m');
        	$qb->join('m.demandeDerog', 'd')
        		->where($qb->expr()->eq('d.id', $idDemande));
        	return $qb->getQuery()->getResult();
        }
    }
    

    Quand je change la valeur de ma liste déroulante Demande voici l'erreur que j'obtiens :

    Entity 'App\Entity\MontantDerog' has no field 'demande'. You can therefore not call 'findByDemande' on the entities' repository

    J'ai tenté de changé le nom de la fonction mais il me dit qu'elles doivent commencer par findBy, get, countBy etc.. Donc je ne sais s'il y a d'autre moyen d'avoir accès à ces informations autrement mais j'aimerais tout de même comprendre pourquoi il ne me prend pas en compte ma fonction dans mon fichier Repository.

    Merci d'avance pour votre attention et réponses !


    • Partager sur Facebook
    • Partager sur Twitter
      17 juillet 2019 à 17:00:15

      Salut !

      Je pense que tu es dans ce cas de la FAQ Symfony, mais avec un nouveau message d'erreur.

      • Partager sur Facebook
      • Partager sur Twitter
        18 juillet 2019 à 9:49:58

        Yay ! Une erreur toute bête, je me doutais qu'il me manquait quelque chose mais sur la documentation officielle je n'avais rien trouvé de tel.

        J'avais ensuite autre erreur de 'infinite loop' au sein de ma relation ManyToMany que j'ai réglé en ajoutant la propriété fetch="EXTRA_LAZY" dans les deux entités et en supprimant une des fonctions get. Maintenant tout semble fonctionner ! 

        Merci beaucoup ! 

        • Partager sur Facebook
        • Partager sur Twitter

        Symfony 4 ManyToMany Query et Repository

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown