我正在尝试动态构建查询。它的初始状态很好。这是应在每个查询中出现的初始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 );
根据我的阅读,第3个参数$append
应保留以前的陈述,但这并没有发生。在Doctrine 1.2中,我可以做这样的事情:
foreach($filter as $col => $val) {
$dql->addWhere($col = ?, array($val));
}
如何动态地向where QueryBuilder添加where子句?
更新
这是一份完整的陈述
$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语句仍然存在。但是当我尝试动态添加它们时,只添加了最后的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 :(得分: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;
}
与大多数其他DQL部分不同,WHERE子句未初始化为数组:
private $_dqlParts = array(
'select' => array(),
'from' => array(),
'join' => array(),
'set' => array(),
'where' => null,
'groupBy' => array(),
'having' => null,
'orderBy' => array()
);
现在,这看起来有点像它的设计,但是Doctrine 2相当新,而且这一点似乎最近在不断发展。就个人而言,我会针对这种行为提出一个错误,看看项目人们说了些什么。如果不出意外,您最终可能会得到改进的文档......
答案 1 :(得分:3)
您可以正常使用 - > andWhere()(它也可以修复您的问题)。
Doctrine 2 QueryBuilder是一个相当创新的概念(因为它混合了程序化和流畅的样式),并且可能存在与之相关的错误。
您应该在代码中注意到的一点:您应该考虑编程,而不是使用 - > add('where',...)。向andX()对象添加更多项目,最后将关联添加到 - > add('where',...)(甚至更好: - > where(...))