Mots-clé : jointure

Symfony 2 et Doctrine et repository : faire un leftJoin avec createQueryBuilder

Comment utiliser createQueryBuilder() ?

La documentation n’est pas très claire sur le sujet. Enfin, disons que si vous êtes comme moi, il va vous manquer des exemples pour mieux comprendre. Je vais essayer de vous faire gagner du temps.

Voilà le problème : j’ai crée un repository pour mes partenaires, que j’ai appelé PartenaireRepository.php.

Dans la plupart des exemples, ils utilisent createQueryBuilder('p'), qui semble pratique (puisqu’il référence immédiatement la table et en fait un alias (dans mon exemple c’est p)

J’ai donc voulu utiliser createQueryBuilder() mais j’ai eu besoin deux jointures d’affilée : les partenaires avaient une ou plusieurs adresses, et ces adresses étaient réliées à des villes. La solution est en fait simple, à partir du moment où on a compris le principe :

    class PartenaireRepository extends EntityRepository
    {
        /**
         * Récupération de tous les partenaires donnés pour un
         * code postal donné.
         */
        public function findAllActiveByCp($cp)
        {
            return $this->createQueryBuilder('p')
                ->leftJoin('p.adresses', 'a')
                ->leftJoin('a.ville', 'v')
                ->where('v.cp=:cp')
                ->setParameter('cp', $cp);
        ... blabla
        }
    }

Ici, le leftJoin('p.adresses', 'a') signifie : dans la classe Partenaire que j’ai déclarée dans le fichier Entity\Partenaire.php, il y a la propriété adresses et tu vas faire une jointure dessus, et cette jointure, tu vas l’aliaser "a". On aura donc, à partir de cette jointure, une référence à une table adresse qu’on pourra utiliser via le "a".

Il est possible de refaire une jointure avec cet alias !

La preuve : la jointure juste après : ->leftJoin('a.ville', 'v') qui signifie, exactement sur le même principe : dans le fichier Entity\Adresse.php, il y a la propriété "ville" et tu vas faire une jointure dessus, et cette jointure, tu vas l’aliaser "v".

Enfin, je termine sur le "where" classique :

->where('v.cp=:cp').

D’après ce que j’ai compris, on ne peut faire des jointures que sur des propriétés qui sont elles même déclarées en tant que jointures. Donc, sur mon fichier « entité » Partenaire, ma jointure est déclarée ainsi :

/**
 * @ORM\ManyToMany(targetEntity="Adresse")
 * @ORM\JoinTable(name="partenaire_adresse",
 *      joinColumns={@ORM\JoinColumn(name="id_partenaire", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="id_adresse", referencedColumnName="id")}
 *      )
 */
private $adresses;

Et de la même façon, sur mon fichier « entité » Ville, ma jointure est déclarée ainsi :

/**
 * @var string
 *
 * @ORM\ManyToOne(targetEntity="Ville")
 * @ORM\JoinColumn(name="id_ville", referencedColumnName="id")
 */
private $ville;

J’espère vous avoir fait gagner du temps, parce que pour moi, la syntaxe n’était pas évidente à trouver.