Php 哪里有问题
在开始之前,我相信我已经尝试了上一篇文章中的所有内容: 因此,我有一个Silex应用程序通过composer使用条令连接到MySQL数据库(条令/dbal 2.2.*) 我尝试运行的查询生成器如下所示:Php 哪里有问题,php,mysql,doctrine-orm,doctrine,silex,Php,Mysql,Doctrine Orm,Doctrine,Silex,在开始之前,我相信我已经尝试了上一篇文章中的所有内容: 因此,我有一个Silex应用程序通过composer使用条令连接到MySQL数据库(条令/dbal 2.2.*) 我尝试运行的查询生成器如下所示: $qb = $this->db->createQueryBuilder(); $stmt = $qb->select('DAY(datefield1) x, COUNT(*) value') ->from('table1', 's') ->join
$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))
查询没有失败,但奇怪的是,它没有包含它应该包含的所有数据
我尝试了->setParameter(':keylist',$keylist)来使用原始数组,但没有成功
我也尝试过这种语法:
$qb->add('where',$qb->expr()->in('r.winner',数组('1'))
但是,这引发了一个错误,因为in方法在expression builder类中不可用
有人能帮我看一下这一点,省得我硬编码SQL吗?DB占位符/参数用于单个值。由于在数组上调用
内爆()
,您正在传入一个单片字符串1,2,3,4
。鉴于:
WHERE t.key IN (:keylist)
然后,此查询将作为
WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
WHERE t.key = '1,2,3,4'
因为它是一个字符串,并且在in
子句中只有一个字符串,所以它是
WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
WHERE t.key = '1,2,3,4'
而不是
WHERE (t.key = 1 OR t.key = 2 OR ....)
你希望是这样。设置多个参数,数组中的每个值对应一个参数,或者直接将字符串嵌入查询中
->andWhere('t.key IN (' . implode(',', $keylist) . ')')
这当然会使您面临sql注入攻击漏洞。DB占位符/参数用于单个值。由于在数组上调用
内爆()
,您正在传入一个单片字符串1,2,3,4
。鉴于:
WHERE t.key IN (:keylist)
然后,此查询将作为
WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
WHERE t.key = '1,2,3,4'
因为它是一个字符串,并且在in
子句中只有一个字符串,所以它是
WHERE t.key IN ('1,2,3,4')
^-------^---note the quotes
WHERE t.key = '1,2,3,4'
而不是
WHERE (t.key = 1 OR t.key = 2 OR ....)
你希望是这样。设置多个参数,数组中的每个值对应一个参数,或者直接将字符串嵌入查询中
->andWhere('t.key IN (' . implode(',', $keylist) . ')')
这当然会使您面临sql注入攻击漏洞。在子句中处理此类
的正确方法非常简单:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->(...)
->andWhere('t.key IN (:keylist)')
->setParameter(':keylist', $keylist)
->getQuery()
->getArrayResult();
我已经用过十几次了,它很有效——doctrine足够聪明,可以处理你的$keylist
数组
另一件事是,我不知道为什么要使用这里冗余的fetchAll
方法-execute()
就足够了。也许这是你问题的根源
我的建议是:尝试在开发模式(app\u dev.php
)下启动操作,并检查您的app/logs/dev.log
——您将发现所有sql查询都已执行。验证数据库是否返回您期望从条令中得到的数据。在
子句中处理此类的正确方法尽可能简单:
$qb = $this->db->createQueryBuilder();
$stmt = $qb->(...)
->andWhere('t.key IN (:keylist)')
->setParameter(':keylist', $keylist)
->getQuery()
->getArrayResult();
->add('where', $qb->expr()->andX(
$qb->expr()->in('r.winner', ':winner')
))
->setParameters(array(
"winner" => $winners,
"billMonth", $month,
// add all params here
));
我已经用过十几次了,它很有效——doctrine足够聪明,可以处理你的$keylist
数组
另一件事是,我不知道为什么要使用这里冗余的fetchAll
方法-execute()
就足够了。也许这是你问题的根源
我的建议是:尝试在开发模式(app\u dev.php
)下启动操作,并检查您的app/logs/dev.log
——您将发现所有sql查询都已执行。验证数据库是否返回您期望从条令中得到的数据。如果您自己构建sql查询,则可以使用DBAL的PARAM_INT_数组类型:
->add('where', $qb->expr()->andX(
$qb->expr()->in('r.winner', ':winner')
))
->setParameters(array(
"winner" => $winners,
"billMonth", $month,
// add all params here
));
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);
如果您自己构建sql查询,则可以使用DBAL的PARAM_INT_数组类型:
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);
您应该通过如下所示的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);
您应该通过如下所示的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);
好的,自从我上次查看以来,这个旧线程已经看到了一些动作,我想确认这个问题已经解决很久了-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);
好的,自从我上次查看以来,这个旧线程已经看到了一些动作,我想确认这个问题已经解决很久了-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);
嗨,马克,谢谢你的回答。我可以看到我对内爆的明显疏忽,并感谢你指出这一点。我不确定谁应该对否决票负责——也许他们会有更好的答案,但现在我将使用你建议的方法,因为它对我很有效。阵列在其他地方硬编码,因此无需注入afaik!谢谢你的回答。我可以看到我对内爆的明显疏忽,并感谢你指出这一点。我不确定谁应该对否决票负责——也许他们会有更好的答案,但现在我将使用你建议的方法,因为它对我很有效。阵列在其他地方硬编码,因此无需注入afaik!谢谢->setParameter(':keylist',$keylist)是正确的语法。D2足够聪明,可以处理参数数组。您确定没有获取所有数据吗?您可以尝试将生成的sql粘贴到数据库连接器中。是的,我已经尝试过了,它会生成不同的数据。事实上,它不返回任何数据,即查询失败:(可能它也受到int/string转换问题的困扰?如果去掉其他where条件,你会得到$keylist记录吗?t.key是字符串还是整数?你没有名为key的数据库列吗?因为这是一个保留字,会导致选择问题。当你说查询失败时,你得到的是实际的sql e吗错误或只是没有记录?您使用的是条令连接对象,而不是orm实体管理器。因此,有一个名为key的列是一个no no。D2不会转义列名。我实际上没有一个名为key的列,对混淆表示歉意-我试图概括该语句,但看看这是如何使它看起来像一个问题的(我不经常在这里发帖)这个专栏叫som