doctrine2关于集合子实体的dql成员

时间:2013-07-17 10:01:22

标签: doctrine-orm dql

使用dql我试图检查实体是否是集合子实体的成员

的entites:

       product
       customer

       customer.orders (collection)
       customer.orders.products (collection, type: product)
       customer.cancellations.productContainers (collection)
       customer.cancellations.productContainers.product (entity, type: product)

客户有多个订单。订单有多个产品。客户有多次取消。取消有多个productContainers。 productContainer有一个产品。

问题

我希望得到所有未被取消的订购产品。

       $qb->select('c, d, p')
       ->from('XyzBundle:Customer', 'c')
       ->leftJoin('c.orders', 'co')
       ->leftJoin('co.products', 'cop')
       ->leftJoin('c.cancellation', 'ca')
       ->leftJoin('ca.productContainers', 'cap')
       ->leftJoin('cap.product', 'capp')
       ->andWhere('cop NOT MEMBER OF capp')

然而这不起作用,因为ca.productContainers是集合字段而不是它的supentity ca.productContainers.product。因此我收到以下错误:

       CRITICAL - Uncaught PHP Exception Doctrine\ORM\Query\QueryException: 
       "[Semantical Error] line 0, col 414 near 'product': Error: Invalid PathExpression. 
       Must be a CollectionValuedAssociationField." at 
       /vagrant/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php line 4 9

有任何建议如何解决这个问题?

1 个答案:

答案 0 :(得分:0)

  

我想获得所有未被取消的订购产品。

假设

  • 您希望这些产品与客户名称一致。
  • 订单包含多个产品
  • productContainer的产品不是多种产品。

-

通过处理上述假设,您可以编写以下DQL来获取您的产品。

WITH

在您的查询构建器之后,您可以添加一个ON a=b AND (WITH) c=d部分,它将作为JOIN子句的另一个条件,如WITH capp.product = cop.product,因此对于cap.product,它将使用附加子句加入取消productContainers产品并关联产品记录。因此,要过滤掉已取消的产品,您可以将其写为SELECT p FROM XyzBundle:Product p LEFT JOIN XyzBundle:ProductContainers pc WITH p.id = pc.product WHERE pc.product IS NULL ,即(取消productContainers)应为空。

如果您只需要产品信息而非其他详细信息,则可以使用更简单的版本

SELECT p.*
FROM product p
    LEFT JOIN product_containers pc ON p.id = pc.product_id
WHERE pc.product_id IS NULL

以上DQL将生成以下等效SQL

SELECT p,c
FROM XyzBundle:Product p
    LEFT JOIN XyzBundle:ProductContainers pc WITH p.id = pc.product
    INNER JOIN XyzBundle:OrderProducts op WITH p.id = op.product
    INNER JOIN op.order o /* property in XyzBundle:OrderProducts which has a reference to order entity */
    INNER JOIN o.customer c /* property in order entity which has a reference to customer entity */
WHERE pc.product IS NULL

另一种将DQL重写为

的方法
{{1}}