thinkphp 6 中多条件查询需用数组(安全,固定字段)或闭包(动态/嵌套逻辑),连续 where 默认为 and;or 必须显式用 whereor 或闭包中 exp;空值需手动过滤,like 要转义通配符并确保 utf8mb4 字符集;性能问题多因索引失效,应避免前导 % 和函数包裹字段,并做好参数白名单校验。

ThinkPHP 6 的 where 方法怎么拼多条件 AND/OR?
直接用数组或闭包写,别硬套字符串拼接。数组方式最安全,适合固定字段;闭包适合动态字段或嵌套逻辑。
常见错误是把多个 where 连续调用当成 OR——其实默认全是 AND。想 OR 必须显式用 whereOr 或闭包里的 exp。
-
where(['status' => 1, 'type' => 'article'])→ 等价于AND status = 1 AND type = 'article' -
where('title', 'like', '%php%')->whereOr('content', 'like', '%php%')→ 正确的 OR 写法 - 复杂组合推荐闭包:
where(function ($query) use ($data) { if (!empty($data['title'])) $query->where('title', 'like', "%{$data['title']}%"); if (!empty($data['cate_id'])) $query->where('cate_id', $data['cate_id']); })
搜索参数为空时,where 会报错还是自动忽略?
不会报错,但空值(如 ''、null、0)会被原样塞进 SQL,可能查出意外结果。比如 where('user_id', '') 在 MySQL 中可能匹配到 0 或隐式转换的记录。
必须手动过滤空值,尤其来自表单的 $_GET 或 $request->param()。
- 用
array_filter($params, function($v) { return $v !== '' && $v !== null; })预处理 - 对数字型字段要额外判断是否为
0是否合法(比如user_id=0可能是有效数据) - 不要依赖
empty(),它会把'0'、0.0、false全干掉,而有些场景下'0'是合法搜索值
LIKE 搜索中文/特殊字符,为什么查不到或报错?
本质是字符集和转义问题。ThinkPHP 默认不自动转义通配符,% 和 _ 会被当 SQL 模糊符,如果用户搜的是 “100%” 就会出错或漏匹配。
更隐蔽的问题是数据库连接没设 UTF8MB4,导致中文被截断或乱码,WHERE 条件根本对不上。
- 用户输入的关键词先过
str_replace(['%', '_'], ['%', '_'], $keyword),再在like中加escape '' - 示例:
where('title', 'like', "%{$escaped}%")->bind(['%'=>$escaped])->extra('escape '\'')(TP6.1+ 支持escape参数) - 确认数据库连接配置中
charset是utf8mb4,且对应字段也是utf8mb4_unicode_ci
性能差、慢查询,是不是 where 写法有问题?
不是写法本身慢,而是没意识到底层生成的 SQL 是否能走索引。比如 where('title', 'like', '%关键词%') 前导 % 直接让索引失效;又或者 whereRaw('DATE(create_time) = CURDATE()') 让日期字段无法用索引。
搜索功能上线前必须看 EXPLAIN,尤其注意 type 是不是 range 或 ref,而不是 ALL。
- 模糊搜索尽量用后缀匹配:
like '关键词%',或引入全文索引(MATCH ... AGAINST) - 时间范围别用函数包裹字段,改用:
whereBetweenTime('create_time', $start, $end) - 复合搜索字段(如 status + cate_id + is_top)建议建联合索引,顺序按筛选频率从高到低排
最常被忽略的点:搜索接口没做参数白名单校验,攻击者传个 order=updatexml(1,concat(0x7e,(select%20user()),0x7e),1) 就能触发报错注入——where 构建再规范,入口不守牢也没用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











