web-dev-qa-db-fra.com

Symfony2 QueryBuilder join ON et WITH différence

Je suis nouveau avec Symfony2 et j'ai construit avec succès ma première jointure via QueryBuilder et Doctrine 2. Probablement c'est une question stupide mais à la fois en ligne et dans les méthodes de Symfony2 je n'ai rien trouvé pour comprendre la différence entre les clauses de jointure "WITH" et "ON".

Par exemple, voici mon code de jointure:

->leftJoin('EcommerceProductBundle:ProductData', 'pdata', 'WITH', 'prod.id = IDENTITY(pdata.product)')

Cela fonctionne bien mais si je mets ON au lieu de WITH j'obtiens l'erreur suivante:

[Erreur de syntaxe] ligne 0, col 200: Erreur: Doctrine\ORM\Query\Lexer :: T_WITH attendue, a obtenu 'ON'

Pourquoi? J'ai vu parmi les objets qu'il y a à la fois les clauses de jointure T_ON et T_WITH, mais quelle est leur différence d'utilisation? À quoi ressemblent leurs utilisations?

31
Roberto Rizzi

@florian vous a donné la bonne réponse mais laissez-moi essayer de l'expliquer par exemple:

Dans sql, les jointures se font comme ceci:

SELECT * FROM category
    LEFT JOIN product ON product.category_id = category.id

(ou quelque chose comme ça)

Maintenant dans Doctrine, vous n'avez pas besoin d'utiliser la clause ON parce que doctrine sait cela à partir des annotations de relations dans vos entités. Donc l'exemple ci-dessus serait:

// CategoryRepository.php
public function getCategoriesAndJoinProducts() 
{
    return $this->createQueryBuilder("o")
        ->leftJoin("o.products", "p")->addSelect("p") 
        ->getQuery()->getResult() ;
}

Les deux récupéreraient toutes les catégories et joindraient les produits qui leur sont associés.

Vient maintenant la clause WITH. Si vous souhaitez joindre uniquement des produits dont le prix est supérieur à 50, vous devez le faire en SQL:

SELECT * FROM category
    LEFT JOIN product ON product.category_id = category.id AND product.price>50

Dans la doctrine:

// CategoryRepository.php
public function getCategoriesAndJoinProductsWithPriceBiggerThan($price) 
{
    return $this->createQueryBuilder("o")
        ->leftJoin("o.products", "p", "WITH", "p.price>:price")
            ->setParameter("price", price)->addSelect("p") 
        ->getQuery()->getResult() ;
}

Donc, en réalité, vous ne devriez jamais, jamais utiliser ON si vous utilisez Doctrine. Si vous avez besoin de quelque chose comme ça, vous pouvez être presque sûr d'avoir vissé autre chose.

48
Zeljko

En théorie, ON vous permet de donner les critères de jointure complets, tandis que WITH permet d'ajouter des critères supplémentaires aux critères par défaut (IMHO).

Mais, ce que DQL permet, c'est d'éviter de donner les critères JOIN:

Il suffit de dire: $qb->leftJoin('prod.pdata', 'pdata');

Et doctrine2 gérera la jointure correctement.

Voici une question connexe à ce sujet: Puis-je utiliser le mot clé "ON" dans DQL ou dois-je utiliser Native Query?

7
Florian