Запрос Doctrine QueryBuilder: имеет несколько ассоциаций

Я создаю форму поиска подержанных автомобилей. В форме пользователь может установить флажки для опций, которые должны быть у автомобиля. Поскольку пользователь может выбрать несколько параметров, мне нужно найти автомобиль, в котором есть все параметры, выбранные пользователем.

Я пытаюсь создать запрос, который проверяет, есть ли у «автомобиля» выбранные параметры. Прямо сейчас я могу проверить, есть ли у автомобиля один из выбранных вариантов, выполнив:

// The options filter is something special, the parameter is passed as a comma separated
// String with options ids
        if($param == 'car.options' && $optionsIds){
            $queryBuilder->leftJoin('car.options', 'option');
            $options        = $queryBuilder->expr()->orX();
            foreach(explode(',', $optionsIds) as $id) {
                $options->add($queryBuilder->expr()->eq('option.id', $id));
            }
            $wheres->add($options);
            continue;
        } 

Но когда я меняю «orX» на «andX», результат всегда возвращается пустым.

Фрагмент кода выше является частью более крупной функции.


person Arne    schedule 22.10.2014    source источник
comment
Вы пробовали $queryBuilder-›andWhere('option.id в (:value)')-›setParameter('value', $value)   -  person Mohammad ZeinEddin    schedule 23.10.2014
comment
Да, я пробовал, но результат тот же, что и выше.   -  person Arne    schedule 23.10.2014


Ответы (1)


Наконец-то мне удалось заставить его работать. Хитрость заключалась в использовании подзапроса:

$carsWithSelectedOptions = $this->getEntityManager()->createQuery('
    SELECT c.id
    FROM Occasions\Model\Bo\Car AS c JOIN c.options o
    WHERE o.id IN ('.$optionsIds.')
    AND c.id = car.id
    GROUP BY c.id
    HAVING COUNT(o.id) >= '.count(explode(',', $optionsIds))
);

$wheres->add($queryBuilder->expr()->exists($carsWithSelectedOptions->getDQL()));

Обратите внимание, что это часть более крупного запроса. Полный запрос приводит к:

SELECT advert, customer, car, country, brand, model 
FROM Occasions\Model\Bo\Advert advert 
LEFT JOIN advert.customer customer 
LEFT JOIN advert.car car 
LEFT JOIN customer.country country 
LEFT JOIN car.model model 
LEFT JOIN car.brand brand 
WHERE EXISTS( 
    SELECT c.id FROM Occasions\Model\Bo\Car AS c 
    JOIN c.options o WHERE o.id IN (2,4,5,51) 
    AND c.id = car.id GROUP BY c.id HAVING COUNT(o.id) >= 4)
AND brand.id = :brandid 
AND model.id = :modelid
AND country.country_code = :countrycountry_code
person Arne    schedule 23.10.2014