Search code examples
phpsymfonydoctrinedql

Doctrine - DQL- multiple ORs nested within one encapsulating AND


I can't find an example of DQL, here's what the semi-pseudocode would look like:

Bring back invoices
- Where company id = 5
AND
    (
      ->where('DATE(i.startPeriod) BETWEEN :startDate AND :endDate')
      ->orWhere('DATE(i.endPeriod) BETWEEN :startDate AND :endDate')
      ->orWhere(':startDate BETWEEN DATE(i.startPeriod) and DATE(i.endPeriod)')
      ->orWhere(':endDate BETWEEN DATE(i.startPeriod) and DATE(i.endPeriod)')
    )

So you have four OR's nested within one encapsulating AND.

Does anyone know how to do that with Doctrine DQL? Nest a bunch of OR's within one giant AND?


Solution

  • You would need to use the Expr() class with the query builder.

    // $qb instanceof QueryBuilder
    
    $qb->select('i')
       ->from('invoices', 'i')
       ->where('c.id = :cid')
       ->andWhere($qb->expr()->orX(
           $qb->expr()->between('i.startPeriod',':startdate',':enddate'),
           $qb->expr()->between('i.endPeriod',':startdate',':enddate'),
    ...
    

    You can read more about the Expr() class in the documentation.

    EDIT:

    Just realized your initial question asked specifically about DQL. You can use parens in DQL to group things, so something like this.

    $query = $em->createQuery(
       'SELECT i FROM Invoices i 
        WHERE c.id = :id 
        AND (
            (i.startPeriod BETWEEN :startDate AND :endDate) 
            OR 
            (i.endPeriod BETWEEN :startDate AND :endDate)
            OR 
            (:startDate BETWEEN i.startPeriod AND i.endPeriod)
            OR
            (:endDate BETWEEN i.startPeriod AND i.endPeriod)
        ) JOIN i.company c');