在开始之前,我相信我已尝试过上一篇文章:How to use WHERE IN with Doctrine 2
所以我有一个Silex应用程序通过作曲家使用Doctrine连接到MySQL数据库(doctrine / dbal 2.2。*)
我尝试运行的查询构建器是:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->select('DAY(datefield1) x, COUNT(*) value')
->from('table1', 's')
->join('s', 'table2', 't', 't.key=s.key')
->where('MONTH(datefield1) = :billMonth')
->andWhere('YEAR(datefield1) = :billYear')
->andWhere('t.key IN (:keylist)')
->groupBy('x')
->orderBy('x', 'asc')
->setParameter(':billMonth', $month)
->setParameter(':billYear', $year)
->setParameter(':keylist', implode(",", $keylist))
->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
参数是(月= 8)(年= 2014)(密钥列表=数组(1,2,3,4))
查询不会失败,但奇怪的是它并不包含它应该包含的所有数据。
我已经尝试过 - > gt; setParameter(':keylist',$ keylist)来使用原始数组,但这并没有用。
我也试过这种语法:
$ qb->添加('其中',$ qb-> expr() - > in(' r.winner',数组(&#39 ;? 1')));
然而,由于in方法在表达式构建器类中不可用,因此引发了错误。
请有人注意这一点,让我不必对我的SQL进行硬编码吗?
答案 0 :(得分:2)
好看,因为这个旧线程已经看到了一些动作,因为我上次查看我想确认问题已经很久解决了 - setParameter中的第三个参数允许您通知Doctrine如何处理数组:
$qb = $this->db->createQueryBuilder();
$stmt = $qb
->select('*')
->from(self::DB_TABLE, 'x')
->where('x.service IN (:services)')
->orderBy('x.session_end', 'DESC')
->addOrderBy('x.direction', 'DESC')
->setParameter(':services', $services, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY)
->setFirstResult($offset)
->setMaxResults($count)
->execute();
$result = $stmt->fetchAll(\PDO::FETCH_ASSOC);
答案 1 :(得分:1)
DB占位符/参数用于单个值。由于在数组上调用1,2,3,4
,您传入的是整体字符串implode()
。给出:
WHERE t.key IN (:keylist)
然后此查询将作为等效的
执行WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
因为它是一个字符串,而IN
子句中只有一个字符串,所以它的功能相当于
WHERE t.key = '1,2,3,4'
而不是
WHERE (t.key = 1 OR t.key = 2 OR ....)
你想要它。设置多个参数,一个用于数组中的每个值,或者直接在查询中嵌入字符串
->andWhere('t.key IN (' . implode(',', $keylist) . ')')
这当然会让你了解sql注入攻击漏洞。
答案 2 :(得分:1)
如果你自己构建sql查询,你可以使用DBAL的PARAM_INT_ARRAY类型:
use Doctrine\DBAL\Connection as DB;
$db->executeQuery('SELECT DAY(datefield1) x, COUNT(*) value
FROM table1 s
JOIN table2 t ON t.key=s.key
WHERE MONTH(datefield1) = :billMonth
AND YEAR(datefield1) = :billYear
AND t.key IN (:keylist)
GROUP BY x
ORDER BY x ASC',
array(':billMonth' => $month, ':billYear' => $year, ':keylist' => $keylist),
array(':billMonth' => \PDO::PARAM_INT, ':billYear' => \PDO::PARAM_INT, ':keylist' => DB::PARAM_INT_ARRAY
)->fetchAll(\PDO::FETCH_ASSOC);
答案 3 :(得分:0)
处理此类IN
子句的正确方法非常简单:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->(...)
->andWhere('t.key IN (:keylist)')
->setParameter(':keylist', $keylist)
->getQuery()
->getArrayResult();
我已经使用了十几次并且它有效 - 教义非常聪明,可以处理你的$keylist
数组。
另一件事是,我不知道你为什么要使用fetchAll
方法,这里的方法是还原剂 - execute()
就足够了。也许这是你问题的根源。
我的建议:尝试以开发模式(app_dev.php
)触发操作并检查app/logs/dev.log
- 您将找到所有执行的SQL查询。验证数据库是否返回了您希望从Doctrine中获取的数据。
答案 4 :(得分:0)
->add('where', $qb->expr()->andX(
$qb->expr()->in('r.winner', ':winner')
))
->setParameters(array(
"winner" => $winners,
"billMonth", $month,
// add all params here
));
答案 5 :(得分:0)
您应该通过如下所示的querybuilder使用in表达式,并更改设置参数的方式:
->andWhere($qb->expr()->in('t.key', ':keylist'))
完整的代码:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->select('DAY(datefield1) x, COUNT(*) value')
->from('table1', 's')
->join('s', 'table2', 't', 't.key=s.key')
->where('MONTH(datefield1) = :billMonth')
->andWhere('YEAR(datefield1) = :billYear')
->andWhere('t.key')
->andWhere($qb->expr()->in('t.key', ':keylist'))
->groupBy('x')
->orderBy('x', 'asc')
->setParameter(':billMonth', $month)
->setParameter(':billYear', $year)
->setParameter(':keylist', $keylist)
->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);