2011-05-12 61 views
3

我試圖動態生成一個查詢。它的初始狀態很好。這是每個查詢應該出現的初始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文檔的查詢生成器的狀態我想使用它應該是太有效的方式。希望確保我做得對,或者如果它是一個錯誤。

+0

您可以粘貼生成的DQL聲明在這裏,一個例子過濾器? – Cobby 2011-05-13 02:19:19

+0

我添加了我正在使用的完整聲明。 – Nathan 2011-05-13 02:43:24

回答

3

你可以使用 - > andWhere()一般(這也將解決你的問題)。

原則2 QueryBuilder是一個相當新穎的概念(因爲它混合了編程風格和流暢風格),並且可能存在與其相關的錯誤。

您應該注意到代碼中的一點:不要用 - > add('where',...)玩,您應該考慮編程。添加更多的項目和X()對象,並在結束時關聯到 - > add('where',...)(或甚至更好: - > where(...))

3

Looking at the code,看起來你正在嘗試做的事情是行不通的,不管這是否記錄在任何地方,或者只是一個缺陷是值得商榷的,我想。

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() 
); 

現在,這看起來有點像它的設計,但原則2是相當新的,這一點似乎已經演變最近。就我個人而言,我會提出一個反對這種行爲的錯誤,並看看項目人員說了些什麼。如果不出意外,你可能最終得到改進文檔...