如何正确使用多个SqlSelect set / add where函数

问题描述

我正在使用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 AGAINSTLIMIT ORDER BY子句,它们始终存在。

在字符串和参数化版本之间出现两种不同的行为,我做错了什么?

解决方法

您使用的第一个示例使用in (?)然后传递值数组将无法正确执行,因为假设?是使用prepare时的一个值。这意味着您正在查询一个等于ResourceTypeID的{​​{1}}。因此,array_value1,array_value2数组中的每个项目都需要有一个占位符(?

该框架确实有一个辅助方法来实现这一点,就像这样:

self::$Filters['Tags']