Gestion des parenthèse avec le QueryBuilder de Doctrine 2

Voici un snippet Doctrine2 pour gérer les parenthèses dans la clause WHERE d'une requete SQL à l'aide du QueryBuilder.

La requête cible est:

 
SELECT m.*, p.*
FROM Message m
INNER JOIN Product p ON m.id = p.mes_id
WHERE  m.delDate IS NULL
AND ( p.module IS NULL OR p.module = 'RAC')

Vous l'aurez compris, la problèmatique se situe au niveau de la dernière ligne de la requête SQL. Ce serait simple à écrire en DQL mais s'il on a besoin de la couche d'abstraction du DQL via l'objet QueryBuidler, ça se complique un peu.
Pour gérer les parenthése avec l'objet QueryBuilder de Doctrine 2, on ne peut pas directement utiliser les méthode where(), andWhere() ou orWhere(). Il faut passer par la création d'une Expression de type OR dans mon cas. Il suffit ensuite d'ajouter les associations champs / valeur puis d'ajouter le tout à la requête avec la méthode where().

 
$em = $this->getDoctrine()->getEntityManager();
$qb = $em->createQueryBuilder();
 
$qb->from('TestBundle:Message', 'm')
       ->join('m.product', 'p')
       ->where('m.delDate IS NULL');
 
//création de l'expression OR
$orModule = $qb->expr()->orx();
$orModule->add($qb->expr()->eq('p.module', ':module'));
$orModule->add($qb->expr()->isNull('p.module'));
 
//Ajout de l'expression à la requête			
$qb->andWhere($orModule)
       ->setParameter('module', 'RAF', \PDO::PARAM_STR);
 
$r = $qb->getQuery()->getResult();

C'est finalement assez simple mais je n'en ai pas trouvé de trace dans la documentation.

Il y a 5 commentaires

  • Maxime Bernard07-16-2012 15:09:09

    Merci pour ce billet ! Il m'a bien dépanné.

  • Mathieu07-27-2012 14:11:08

    Merci beaucoup !

    c'est exactement ce dont j'avais besoin !

  • Ontsy10-29-2012 08:24:15

    Mille merci,
    J'ai cherché partout mais j'ai trouvé ce qu'il me faut.

  • Yann05-13-2014 10:40:29

    Merci pour ce tuto.
    ça fonctionne parfaitement.

  • Nico06-11-2014 22:05:26

    Post toujours d'actualité, documentation officielle toujours peu claire à sujet ... Merci beaucoup ;)

    Il est bien sur possible d'effectuer des (x = x AND a = a) OR (x = y AND a = b) grâce à :
    $andMod = $qb->expr()->andX();
    $andMod->addMultiple(array(
    $qb->expr()->eq('i.class_name', ':class'.$cpt),
    $qb->expr()->in('i.id_in_scope', $ids)
    ));
    $qb->setParameter(':class'.$cpt, $class);
    $qb->orWhere($andMod);
    ...