Где заявления не добавляются - PullRequest
3 голосов
/ 13 мая 2011

Я пытаюсь построить запрос динамически. Это начальное состояние в порядке. Это начальное условие where, которое должно присутствовать в каждом запросе

$qb->add('where', $qb->expr()->andx(
    $qb->expr()->eq('s.competitor', $competitor),
    $qb->expr()->eq('s.ignored', $ignored),
    $qb->expr()->eq('s.id', $params['s_id']),
    $qb->expr()->eq('s.id', 'k.targetSite')
), true);

Но приложение, которое я создаю, позволяет пользователям фильтровать. Когда это произойдет, я хочу добавить дополнительные предложения where в мой конструктор запросов. Когда эта строка выполняется позже в коде, она перезаписывает вышеприведенный оператор where.

$qb->add('where',  $qb->expr()->like($col, $val), true );

Из того, что я прочитал, третий параметр $append должен сохранить предыдущие утверждения, но этого не происходит. В Doctrine 1.2 я мог бы просто сделать что-то вроде этого:

foreach($filter as $col => $val) {
    $dql->addWhere($col = ?, array($val));
}

Как динамически добавлять предложения where в мой QueryBuilder?

Обновление

Вот полное изложение

$where = array('col' => 'k.text', 'val' => 'some word%');

$qb = $this->entityManager->createQueryBuilder()
    ->select('s, sc')
    ->from('Dashboard\Entity\Section', 'sc')
    ->innerJoin('sc.keyword', 'k')
    ->innerJoin('sc.site', 's')
    ->leftJoin('k.keywordCategory', 'kc')
    ->leftJoin('k.keywordSubCategory', 'ksc');

$qb->add('where', $qb->expr()->andx(
    $qb->expr()->eq('s.competitor', $competitor),
    $qb->expr()->eq('s.ignored', $ignored),
    $qb->expr()->eq('s.id', $params['s_id']),
    $qb->expr()->eq('s.id', 'k.targetSite')
), true);

if ($where) {
    $qb->add('where', $qb->expr()->andx(
             $qb->expr()->like($where['col'], $where['val'])
    ), true);
}

$qb->addGroupBy('k.id');
    $qb->addGroupBy('s.id');

$qb->setFirstResult( $params['start'] )
   ->setMaxResults( $params['limit'] );

$q = $qb->getQuery();
echo $q->getSql();

А на выходе

SELECT s0_.id AS id0, k1_.id AS id1, k1_.name AS name2, k2_.id AS id3, k2_.name AS   name4, k3_.id AS id5, k3_.text AS text6, k3_.search_vol AS search_vol7, s4_.id AS id8, s4_.sub_domain AS sub_domain9, MIN(s0_.rank) AS sclr10, MAX(s0_.created) AS sclr11 
FROM section s0_ 
INNER JOIN keyword k3_ ON s0_.k_id = k3_.id 
INNER JOIN site s4_ ON s0_.s_id = s4_.id 
LEFT JOIN keyword_category k1_ ON k3_.k_cat_id = k1_.id 
LEFT JOIN keyword_sub_category k2_ ON k3_.k_subcat_id = k2_.id 
WHERE k3_.text LIKE 'some word%' 
GROUP BY k3_.id, s4_.id LIMIT 25 OFFSET 0

Если я не добавлю в это предложение if ($where), то первые andx, где операторы все еще на месте. Но когда я пытаюсь динамически добавить их, добавляется только последний оператор WHERE, все остальные очищаются. Я должен также добавить, что я тоже так пробовал.

if ($where) {
    $qb->add('where', $qb->expr()->like($where['col'], $where['val']), true);
}

Я могу успешно использовать

$qb->andWhere( $qb->expr()->like($where['col'], $where['val']) );

Но документы API для Query Builder указывают, как я пытаюсь их использовать, также должно быть допустимо. Хотел убедиться, что я все делал правильно, или это была ошибка.

Ответы [ 2 ]

3 голосов
/ 17 мая 2011

Вы можете использовать -> иWhere () как обычно (и это также исправит вашу проблему).

Doctrine 2 QueryBuilder - это довольно инновационная концепция (потому что она сочетает в себе как программный, так и свободный стиль), и с ней, вероятно, связаны ошибки.

Один момент, который вы должны заметить в своем коде: вместо того, чтобы играть с -> add ('где', ...), вы должны думать программно. Добавьте больше элементов к объекту andX () и в конце свяжите с -> add ('where', ...) (или даже лучше: -> where (...))

3 голосов
/ 16 мая 2011

Глядя на код , кажется, что то, что вы пытаетесь сделать, не сработает, хотя, думаю, задокументировано ли это где-то или это просто ошибка, я думаю.

В add() передаваемая вами часть DQL кажется добавленной только в том случае, если она уже сохранена в массиве в конструкторе запросов:

   $isMultiple = is_array($this->_dqlParts[$dqlPartName]);
   ...

    if ($append && $isMultiple) {
        if (is_array($dqlPart)) {
            $key = key($dqlPart);

            $this->_dqlParts[$dqlPartName][$key][] = $dqlPart[$key];
        } else {
            $this->_dqlParts[$dqlPartName][] = $dqlPart;
        }
    } else {
        $this->_dqlParts[$dqlPartName] = ($isMultiple) ? array($dqlPart) : $dqlPart;
    }

И предложение WHERE, в отличие от большинстваиз других частей DQL не инициализируется в массиве:

private $_dqlParts = array(
    'select'  => array(),
    'from'    => array(),
    'join'    => array(),
    'set'     => array(),
    'where'   => null,
    'groupBy' => array(),
    'having'  => null,
    'orderBy' => array()
);

Теперь это выглядит как дизайн, но Doctrine 2 довольно нова, и этот бит, кажется, развивается в последнее время.Лично я бы поднял ошибку против такого поведения и посмотрел бы, что говорят люди проекта.Если ничего другого, вы можете получить улучшенную документацию ...

...