Член doctrine2 dql, входящий в состав сущностей коллекции - программирование
Подтвердить что ты не робот

Член doctrine2 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)

Клиент имеет несколько заказов. Заказ имеет несколько продуктов. Клиент имеет несколько аннулирования. Отмена имеет несколько продуктов. Продукт имеет контейнер.

Проблема

Я хочу получить все упорядоченные продукты, которые не будут отменены.

       $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 - это поле сбора, а не его суффикс 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

Любые предложения, как это решить?

4b9b3361

Ответ 1

Я хочу получить все упорядоченные продукты, которые не будут отменены.

Предположения

  • Вам нужны эти продукты вместе с именем клиента.
  • Заказ имеет несколько продуктов
  • У продуктаContainer есть продукт, не имеющий нескольких продуктов.

-

Соблюдая вышеприведенные предположения, вы можете написать следующий DQL, чтобы получить ваши продукты.

SELECT c,cop.product /* cop.product => refers to property which has an association with product entity */
FROM XyzBundle:Customer c
    LEFT JOIN c.orders co
    LEFT JOIN co.products cop
    LEFT JOIN c.cancellation ca
    LEFT ca.productContainers cap
    LEFT cap.product capp WITH capp.product = cop.product
WHERE capp.product IS NULL

Следуя за построителем запросов, вы можете добавить часть WITH, которая будет вести себя как еще одно условие для предложения JOIN, например ON a=b AND (WITH) c=d So для WITH capp.product = cop.product, оно присоединяет продукт отмены продуктаContainers с дополнительным предложением и связывает запись продукта. Таким образом, чтобы отфильтровать отмененные продукты, вы можете записать его как cap.product i.e(продукт отмены продуктаContainers) должен быть нулевым.

Если вам нужна только информация о продуктах, а не другие данные, вы можете использовать более простую версию

SELECT p
FROM XyzBundle:Product p
    LEFT JOIN XyzBundle:ProductContainers pc WITH p.id = pc.product
WHERE pc.product IS NULL

Над DQL будет генерироваться следующий эквивалентный SQL

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

Другой способ переписать ваш DQL как

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