ThinkPHP5多字段模糊搜索必须用whereOr或闭包实现OR逻辑,不可仅用where;需手动转义LIKE通配符、trim空格、分页时透传query参数,否则易导致全表扫描、SQL注入或参数丢失。

ThinkPHP5 的搜索接口模糊查询,核心就一条:别直接拼 SQL,用 whereOr 或快捷查询符 | 处理多字段 LIKE,否则容易漏匹配、SQL 报错或被注入。
多字段模糊搜索用 whereOr 还是 where?
当用户输入一个关键词,想在 user_login 或 user_nickname 里都查——这是典型的 OR 关系,必须用 whereOr,不能只写 where。
-
where(['user_login|user_nickname', 'like', "%{$keyword}%"])看似简洁,但这是「快捷查询」语法,底层仍会转成 OR,可读性差且字段名带|容易和真实字段名冲突(比如字段名含竖线) - 更稳妥的是显式用闭包 +
whereOr:$query->where('user_login', 'like', "%{$keyword}%") ->whereOr('user_nickname', 'like', "%{$keyword}%"); - 如果还要叠加其他 AND 条件(如
status = 1),得把whereOr放在闭包里,否则整个条件逻辑会错乱
input('get.keyword') 没过滤会出什么问题?
不校验直接进查询,轻则空结果、重则报错甚至 SQL 注入。TP5 虽有基础过滤,但 LIKE 中的百分号 % 和下划线 _ 是通配符,必须转义。
- 用
str_replace(['%', '_'], ['%', '_'], $keyword)手动转义,再加escape => true参数:->where('user_login', 'like', "%{$escapedKeyword}%", ['escape' => '\']) - 别依赖
input()的默认 filter,它不处理 LIKE 通配符 - 空字符串或纯空白字符要提前
trim()判断,避免执行WHERE name LIKE "%%"这种全表扫
分页时 URL 参数丢失怎么办?
paginate() 默认只保留当前页参数,关键词一翻页就没了。必须手动透传查询参数。
立即学习“PHP免费学习笔记(深入)”;
- 在控制器里构造
query配置:->paginate(10, false, ['query' => request()->param()])
-
request()->param()包含所有 GET 参数,但注意别把敏感字段(如 token)也透传过去 - 模板里用
{$page|raw}渲染分页 HTML,否则链接里的keyword=xxx会被 HTML 转义失效
真正难的不是写对一行 whereOr,而是每个关键词入口都要统一处理转义、空值、分页透传和字段权限——漏掉任意一环,线上就可能查慢、查错或被利用。



















