Doctrine2 Query Builder 中的函数顺序重要吗?

Gre*_*ina 5 php mysql sql orm doctrine-orm

我有两个实体OrderShipment. 每个订单有一个发货,反之亦然。我正在尝试查询待处理的订单。以下是标准:

  • 订单已发送(不仅仅是保存)
  • 订单尚未取消
  • 该订单没有发货
  • 或 订单有发货
    • 但是 Shipment 还没有发送(刚刚保存了)
    • 如果发货已发送,则它也已被取消

这是我提出的查询:

<?php

use Doctrine\ORM\EntityRepository;

class OrderRepository extends EntityRepository
{

    public function findPending($id)
    {
        return $this->createQueryBuilder('o')
            ->addSelect('s')
            ->leftJoin('MyApp\\Model\\Entity\\Shipment', 's')
            ->orderBy('o.date_sent', 'DESC')

            // Order has been sent
            ->where($qb->expr()->neq('o.date_sent',':date_sent'))
            ->setParameter('date_sent', '0000-00-00 00:00:00')

            // Order was not cancelled
            ->where($qb->expr()->eq('o.date_cancelled',':date_cancelled'))
            ->setParameter('date_cancelled', '0000-00-00 00:00:00')

            // Order does not have a shipment
            ->andWhere($qb->expr()->isNull('s.order'))

            // OR Shipment has not been sent
            ->orWhere($qb->expr()->neq('s.date_sent', ':ship_date_sent'))
            ->setParameter('ship_date_sent', '0000-00-00 00:00:00')

            // AND Shipment has not been cancelled
            ->andWhere($qb->expr()->eq('s.date_cancelled',':ship_date_cancelled'))
            ->setParameter('ship_date_cancelled', '0000-00-00 00:00:00')

            ->setMaxResults(6)
            ->getQuery()
            ->getResult();
    }
}
Run Code Online (Sandbox Code Playgroud)

它似乎有效,但我没有太多数据可以对其进行测试。我很担心最后一个->andWhere()语句,看看Shipment 有没有被取消。如果我使用“and”,我担心它只会返回带有“尚未发送且尚未取消”的货件的订单,而不是“尚未发送或已发送但尚未取消”的订单。如果我更改为->andWhere()->orWhere()我认为它将返回带有“已发送但未取消”的货件的订单。

我主要关心的是查询函数的顺序如何影响查询。还有,应该where()只用一次吗?我不明白之间的差别where()andWhere()

如果我的问题不够清楚,请告诉我,我会更新。

先感谢您。

更新

我挖得更深一些,并提出了这个新查询。我认为哪个可行?

public function findPending($id)
{
    $qb = $this->createQueryBuilder('o')
        ->addSelect('s')
        ->leftJoin('MyApp\\Model\\Entity\\Shipment', 's')
        ->orderBy('o.date_sent', 'DESC')

        // Order has been sent and was not cancelled
        ->where($qb->expr()->andX(
            $qb->expr()->eq('o.date_cancelled','0000-00-00 00:00:00'),
            $qb->expr()->neq('o.date_sent','0000-00-00 00:00:00')
            ))

        ->andWhere($qb->expr()->orX(
            // Order doesn't have a shipment
            $qb->expr()->isNull('s.order'),
            // OR Order has a shipment
            $qb->expr()->orX(
                // Shipment has not been sent
                $qb->expr()->eq('s.date_sent','0000-00-00 00:00:00'),
                // OR Shipment has been sent AND it was cancelled
                $qb->expr()->andX(
                    $qb->expr()->neq('s.date_sent','0000-00-00 00:00:00'),
                    $qb->expr()->eq('s.date_cancelled','0000-00-00 00:00:00')
                    )
                )
            ))

        ->setMaxResults(6)
        ->getQuery()
        ->getResult();
    return $qb;
}
Run Code Online (Sandbox Code Playgroud)

小智 0

是的,where只能使用一次,因此如果andWhere(或orWhere)是有条件的但可以使用多次,您可能应该使用where 1=1