使用MATCH()AGAINST()和PDO的奇怪行为(语法错误)

时间:2016-02-24 15:25:12

标签: php mysql pdo full-text-search lumen

我正在处理一个在FULLTEXT索引上使用MATCH()AGAINST()的查询。

奇怪的是,查询在PHP的PDO中不起作用,但 适用于HeidiSQL甚至MySQL控制台(mysql -u [...])

这是我正在处理的查询:

SELECT *
FROM `announcements`
WHERE MATCH (`name`, `email`, `trademark`, `model`, `phone`, `city`) AGAINST ('+Ravenna*' IN BOOLEAN MODE)

这是PDO的错误:

  

SQLSTATE [42000]:语法错误或访问冲突:1064 SQL语法中有错误;检查与MySQL服务器版本对应的手册,以便在

附近使用正确的语法
第1行

'?) against ('?' in boolean mode))'

SELECT count(*) AS AGGREGATE
FROM `announcements`
WHERE `archived_at` IS NULL
  AND (MATCH (`name`, `email`,  `trademark`, `model`, `phone`, `city`) against ('+Ravenna*' IN boolean MODE))

修改

这是导致错误的函数:

[...]

$this->customQueries[] = function ($query) use ($words) {

    $columnsToSearch = array_map(function ($key) {
        return "`{$key}`";
    }, [
        'name', 'email', 'trademark', 'model', 'phone', 'city'
    ]);

    $matchColumns = implode(', ', $columnsToSearch);
    $againstWords = value(function () use ($words) {
        $string = "";

        foreach ($words as $word) {
            $string .= "+{$word}* ";
        }

        $string = trim($string);

        return $string;
    });

    // This is specifically the function that causes the error.
    $query->whereNested(function ($q) use ($matchColumns, $againstWords) {
        $q->whereRaw("match (?) against ('?' in boolean mode)", [$matchColumns, $againstWords]);
    });
};

我无法理解为什么它只适用于PDO。

我已经在StackOverflow上搜索过,所有单引号都已经过检查。

1 个答案:

答案 0 :(得分:1)

您不能将逗号分隔的列名字符串作为参数插入到预准备语句中。相反,您应该将它们注入SQL语句中,而不是将它们作为参数传递。

其次,您不应该使用引号包装占位符(?)。

所以尝试修改你的代码:

$query->whereNested(function ($q) use ($matchColumns, $againstWords) {
    $q->whereRaw("match ($matchColumns) against (? in boolean mode)", [$againstWords]);
 });

您可能认为在这样的SQL字符串中注入$matchColumns是不好的,但由于您可以完全控制该值,因此没有风险(SQL注入)。