问题描述
我正在使用SilverStripes sqlSelect类和一些可选的(前端)过滤器将SQL查询拼凑在一起。
尝试对参数使用addWhere()
时,查询无结果。例如:
$sql->useConjunction();
$sql->addWhere(['SiteTree.ClassName' => 'ResourcePage']);
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags','ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Tags.ResourceTagID IN (?)' => implode(',',self::$Filters['Tags'])]);
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types','ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere(['ResourcePage_Types.ResourceTypeID IN (?)' => implode(',self::$Filters['Types'])]);
}
如果我将其视为字符串,则会得到结果(就像我期望使用手动sql进行测试一样)。例如:
$sql->useConjunction();
$sql->addWhere("SiteTree.ClassName = 'ResourcePage'");
if (self::$Filters['Tags'])
{
$sql->addLeftJoin('ResourcePage_Tags','ResourcePage_Tags.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Tags.ResourceTagID IN ('.implode(',self::$Filters['Tags']).')');
}
if (self::$Filters['Types'])
{
$sql->addLeftJoin('ResourcePage_Types','ResourcePage_Types.ResourcePageID = SiteTree.ID');
$sql->addWhere('ResourcePage_Types.ResourceTypeID IN ('.implode(',self::$Filters['Types']).')');
}
使用$sql->__toString()
找到的生成的(简化的)查询是:
SELECT
disTINCT SiteTree.*
FROM
SiteTree
LEFT JOIN
"ResourcePage_Tags" ON ResourcePage_Tags.ResourcePageID = SiteTree.ID
LEFT JOIN
"ResourcePage_Types" ON ResourcePage_Types.ResourcePageID = SiteTree.ID
WHERE
(SiteTree.ClassName = ?)
AND (ResourcePage_Tags.ResourceTagID IN (?))
AND (ResourcePage_Types.ResourceTypeID IN (?))
'ResourcePage',1 => '38'
2 => '5,4'
查询中省略的部分是一些MATCH AGAINST
和LIMIT ORDER BY
子句,它们始终存在。
在字符串和参数化版本之间出现两种不同的行为,我做错了什么?
解决方法
您使用的第一个示例使用in (?)
然后传递值数组将无法正确执行,因为假设?
是使用prepare时的一个值。这意味着您正在查询一个等于ResourceTypeID
的{{1}}。因此,array_value1,array_value2
数组中的每个项目都需要有一个占位符(?
。
该框架确实有一个辅助方法来实现这一点,就像这样:
self::$Filters['Tags']