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

How to correctly use multiple SqlSelect set/add where functions

我正在使用 SilverStripes SQLSelect class 和一些可选的(前端)过滤器拼凑一个 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 等于 array_value1,array_value2。因此,self::$Filters['Tags'] 数组中的每个项目都需要一个占位符 (?)。

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

$placeholders = DB::placeholders(self::$Filters['Tags'])
$query->addWhere([
  "ResourcePage_Types.ResourceTypeID IN ($placeholders)" => self::$Filters['Tags']
]);