
本文讲解如何安全、准确地将逗号分隔的关键词字符串拆分为数组,并动态构建支持多关键词模糊匹配的mysql查询语句,重点解决因空格未被识别导致的where条件失效问题。
在PHP中,将用户输入的关键词字符串(如 "paper, glue, discount, bulk")拆解为数组并用于构建动态SQL查询是常见需求。但一个极易被忽略的细节会导致整个查询逻辑失效:字符串分隔符未与实际格式严格匹配。
你当前的代码使用了:
$new_search = preg_split("/,/", $my_search);这会将 "paper, glue, discount, bulk" 拆分为:
['paper', ' glue', ' discount', ' bulk']
注意:每个后续元素开头都带有一个前导空格(' glue' 而非 'glue')。当拼接进 LIKE '%$value%' 时,实际生成的是 LIKE '% glue%' —— 数据库中几乎不可能存在以空格开头的关键词,因此该条件恒为 FALSE。而由于你初始条件是 LIKE '%offers%' OR ...,一旦 '%offers%' 在表中不存在(或字段值不含 "offers"),整个 OR 链因逻辑短路失效,最终可能退化为全表扫描(尤其当 WHERE 子句因语法/语义错误未能有效过滤时),表现为“返回所有行”。
立即学习“PHP免费学习笔记(深入)”;
✅ 正确做法是按 ,(逗号+空格) 精确分割:
$my_search = "paper, glue, discount, bulk";
$new_search = preg_split("/, /", $my_search); // 注意空格
// 结果:['paper', 'glue', 'discount', 'bulk']更健壮的写法(兼容多余空格、首尾空格):
$my_search = trim($my_search); // 去首尾空格
$new_search = array_map('trim', preg_split('/,\s*/', $my_search)); // 支持逗号后任意空白
$new_search = array_filter($new_search, 'strlen'); // 过滤空元素构建查询时,还需注意以下关键点:
? 避免SQL注入风险:直接拼接 $value 极其危险。应使用预处理语句或至少对关键词进行转义:
// 推荐:使用 PDO 预处理(更安全)
$placeholders = str_repeat('?,', count($new_search) - 1) . '?';
$sql = "SELECT * FROM clients_personal WHERE likes LIKE ? " .
str_repeat(" OR likes LIKE ? ", count($new_search) - 1);
$stmt = $pdo->prepare($sql);
$params = array_map(fn($v) => "%{$v}%", $new_search);
$stmt->execute($params);? 逻辑修正:你原始SQL以 WHERE likes LIKE '%offers%' OR ... 开头,但 'offers' 并不在 $new_search 中 —— 它是硬编码的额外条件。若本意是仅匹配用户输入的关键词,应从 WHERE 后直接开始拼接:
if (empty($new_search)) {
die("No keywords provided");
}
$conditions = [];
$params = [];
foreach ($new_search as $value) {
$conditions[] = "likes LIKE ?";
$params[] = "%{$value}%";
}
$mmsql = "SELECT * FROM clients_personal WHERE " . implode(' OR ', $conditions);
$stmt = $conn->prepare($mmsql);
$stmt->execute($params);? 性能提醒:LIKE '%keyword%' 无法使用索引,大数据量下性能较差。如需高效搜索,建议考虑全文索引(FULLTEXT)或专用搜索引擎(如Elasticsearch)。
总结:字符串分割必须与原始格式一致;动态SQL务必防御注入;逻辑起点(WHERE 后首个条件)需清晰明确;生产环境优先采用预处理语句。











