Bonjour,

J'ai un souci dans un projet Symfony où j'ai une liasion Many to Many (n:m) bidirectionnelle.

J'ai donc trois tables :

  • Livres
  • Livres_has_tags
  • Tags

J'ai ainsi deux entités : Livres et Tags. Le but est de pouvoir afficher les tags par livre et aussi les livres par tag. Voici la partie concernée de mes entités:
/**

  • Tags
  • @ORM\Table(name="tags")
  • @ORM\Entity(repositoryClass="FrontBundle\Repository\TagsRepository")
    */
    class Tags {

    /**

    • @var \Doctrine\Common\Collections\Collection
    • @ORM\ManyToMany(targetEntity="Livres", inversedBy="tagID")
    • @ORM\JoinTable(name="tags_has_livres",
    • joinColumns={
    • @ORM\JoinColumn(name="tagID", referencedColumnName="id")
    • },
    • inverseJoinColumns={
    • @ORM\JoinColumn(name="livreIsbn", referencedColumnName="isbn")
    • }
    • )
      */
      private $livreIsbn;
      }

/**

  • Tags
  • @ORM\Table(name="tags")
  • @ORM\Entity(repositoryClass="FrontBundle\Repository\TagsRepository")
    */
    class Tags {

    /**

    • @var \Doctrine\Common\Collections\Collection
    • @ORM\ManyToMany(targetEntity="Livres", inversedBy="tagID")
    • @ORM\JoinTable(name="tags_has_livres",
    • joinColumns={
    • @ORM\JoinColumn(name="tagID", referencedColumnName="id")
    • },
    • inverseJoinColumns={
    • @ORM\JoinColumn(name="livreIsbn", referencedColumnName="isbn")
    • }
    • )
      */
      private $livreIsbn;

/**

  • Livres
  • @ORM\Table(name="livres", uniqueConstraints={@ORM\UniqueConstraint(name="isbn_UNIQUE", columns={"isbn"})}, indexes={@ORM\Index(name="fk_livres_auteurs_idx", columns={"auteurID"}), @ORM\Index(name="fk_livres_editeurs1_idx", columns={"editeurID"})})
  • @ORM\Entity
    */
    class Livres{

    /**

    • @var \Doctrine\Common\Collections\Collection
    • @ORM\ManyToMany(targetEntity="Tags", mappedBy="livreIsbn")
    • */
      private $tagID;
      }

Voici l'action de mon TagsController.php dont le but serait, dans un premier temps d'afficher les tags par livre. Je précise que la valeur de $isbn est envoyée depuis la vue qui affiche la liste de livres.

public function listeParLivreAction($isbn){

$repository = $this->getDoctrine()->getManager()->getRepository('FrontBundle:tags');

  $tags = $repository->vaChercherTagsParLivre($isbn);

  return $this->render('FrontBundle:Tags:listeParLivre.html.twig',
                        array('tags'=>$tags));

}<br><br>

Et voici mon TagsRepository.php

public function vaChercherTagsParLivre($isbn){

  $queryBuilder = $this->createQueryBuilder('tags');

   $queryBuilder->where('tags.livreIsbn = :isbn')
               ->setParameter('isbn',$isbn);

   $query = $queryBuilder->getQuery();

   $result = $query->getResult();

   return $result;

}

Mais ça ne marche pas comme vous vous en doutez bien :-( Je précise que je débute sur Symfony, j'ai encore beaucoup du mal avec les requêtes via le createQueryBuilder de Doctrine.

Je vous remercie par avance de votre aide. Aidez-moi s'il vous plait.

2 réponses


Bonjour,
Pourquoi faire compliqué, quand c'est si simple ?

Livre :

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Livre
 *
 * @ORM\Table(name="livre")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\LivreRepository")
 */
class Livre
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Tags", inversedBy="livres")
     * @ORM\JoinTable(name="livres_has_tags")
     */
    private $tags;
     /**
     * @var string
     * @ORM\Column(name="isbn", length=15, type="string")
     */
    private $isbn;

    /**
     * @return string
     */
    public function getIsbn()
    {
        return $this->isbn;
    }

    /**
     * @param string $isbn
     * @return Livre
     */
    public function setIsbn($isbn)
    {
        $this->isbn = $isbn;

        return $this;
    }

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->tags = new ArrayCollection();
    }

    /**
     * Add tag
     *
     * @param Tags $tag
     *
     * @return Livre
     */
    public function addTag(Tags $tag)
    {
        $this->tags[] = $tag;

        return $this;
    }

    /**
     * Remove tag
     *
     * @param Tags $tag
     */
    public function removeTag(Tags $tag)
    {
        $this->tags->removeElement($tag);
    }

    /**
     * Get tags
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getTags()
    {
        return $this->tags;
    }
}

Tag :

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * Tags
 *
 * @ORM\Table(name="tags")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\TagsRepository")
 */
class Tags
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var ArrayCollection
     * @ORM\ManyToMany(targetEntity="Livre", mappedBy="tags")
     */
    private $livres;

    /**
     * Get id
     *
     * @return int
     */
    public function getId()
    {
        return $this->id;
    }
    /**
     * Constructor
     */
    public function __construct()
    {
        $this->livres = new ArrayCollection();
    }

    /**
     * Add livre
     *
     * @param Livre $livre
     *
     * @return Tags
     */
    public function addLivre(Livre $livre)
    {
        $this->livres[] = $livre;

        return $this;
    }

    /**
     * Remove livre
     *
     * @param Livre $livre
     */
    public function removeLivre(Livre $livre)
    {
        $this->livres->removeElement($livre);
    }

    /**
     * Get livres
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getLivres()
    {
        return $this->livres;
     }

Dans controller :

$livre = $this->getDoctrine()->getRepository("AppBundle:Livre")->findOneByIsbn($isbn);
// équivaut à : $livre = $this->getDoctrine()->getRepository("AppBundle:Livre")->findOneBy(["isbn"=>$isbn]);
if(!$livre){
    // erreur livre non trouvé
}

$tags = $livre->getTags();

A adapter aux besoins ...

LISEZ LA DOCUMENTATION ! on ne le dira jamais assez

relation ManyToMany

doctrine2

Bonjour Nico41, je vous remercie de votre réponse.
Mes entités n'ont pas de souci. Elles sont générées. Mon but est d'éviter les find ou findAll() ou encore findBy mais de passer par une requête personnalisée via le repository. C'est dans cette reqûete que je n'arrive pas à utiliser correctement la syntaxe en DQL.
Bonne soirée.