基于标签展示相关文章的SQL语句修正求助
解决多标签相似文章查询无结果的问题
问题根源
原代码存在两个关键问题:
- 直接拼接标签到SQL语句,存在SQL注入风险,若标签包含特殊字符(如
'、%)会破坏SQL语法,导致查询失败; - 未给OR条件组添加括号,虽逻辑上AND优先级更高,但易引发歧义,且FIND_IN_SET的使用方式可能有误。
修复方案(两种可选)
方案1:安全的LIKE匹配(兼容带空格的标签格式)
保留LIKE模糊匹配逻辑,同时通过参数绑定避免注入问题:
$tagsArray = array_map('trim', explode(',', $tags)); $conditions = []; $data = ['id' => $id]; foreach ($tagsArray as $index => $tag) { $paramKey = ":tag{$index}"; // 用CONCAT拼接通配符,避免参数绑定失效 $conditions[] = "tags LIKE CONCAT('%', {$paramKey}, '%')"; $data[$paramKey] = $tag; } $tagsString = implode(' OR ', $conditions); // 给OR条件组加括号,明确逻辑优先级 $sql = $this->conn->prepare("SELECT * FROM ps_objects WHERE id != :id AND ({$tagsString}) ORDER BY date DESC LIMIT 5;"); $sql->execute($data); $result = $sql->fetchAll();
方案2:FIND_IN_SET精确匹配(适合无空格的逗号分隔标签)
如果tags字段是严格无空格的逗号分隔格式(如john,Leo,Mike),用FIND_IN_SET可避免LIKE的部分匹配误判(比如不会把johnny识别为含john的标签):
$tagsArray = array_map('trim', explode(',', $tags)); $conditions = []; $data = ['id' => $id]; foreach ($tagsArray as $index => $tag) { $paramKey = ":tag{$index}"; $conditions[] = "FIND_IN_SET({$paramKey}, tags)"; $data[$paramKey] = $tag; } $tagsString = implode(' OR ', $conditions); $sql = $this->conn->prepare("SELECT * FROM ps_objects WHERE id != :id AND ({$tagsString}) ORDER BY date DESC LIMIT 5;"); $sql->execute($data); $result = $sql->fetchAll();
注意:若
tags字段里的标签带空格(如john, Leo, Mike),需修改FIND_IN_SET写法去除空格:$conditions[] = "FIND_IN_SET({$paramKey}, REPLACE(tags, ' ', ''))";
原代码多标签无结果的原因
大概率是标签包含特殊字符(如空格、引号),直接拼接导致SQL语法错误;或是FIND_IN_SET使用时未正确处理空格/参数绑定,导致匹配逻辑失效。
内容的提问来源于stack exchange,提问作者Михаил Горячев
相关产品推荐
相关产品推荐

