#php #silverstripe
#php #silverstripe
Вопрос:
Я собираю SQL-запрос, используя класс SilverStripes SQLSelect с некоторыми дополнительными фильтрами (frontend).
При попытке использовать 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
, которые всегда присутствуют.
Что я сделал не так, чтобы получить два разных поведения между string и параметризованной версией?
Ответ №1:
Первый пример, который у вас был, который использовал 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']
]);
Комментарии:
1. Ну ладно. Я видел этот пример
DB::prepared_query('DELETE FROM "SiteTree" WHERE "SiteTree"."ShowInMenus" = ?', [0]);
в документах. Приветствую это.