thinkphp的where数组写法需注意:多条件and默认全等,like/in等需显式运算符;闭包中必须用$query->where()且顺序影响sql括号逻辑;空数组不报错但清空条件;动态条件推荐when方法而非松散判断。

ThinkPHP 的 where 数组写法容易漏掉嵌套逻辑
多条件 AND 查询看似简单,但一写成 ['status' => 1, 'type' => 'user'] 就默认全等,没法表达 LIKE、IN 或范围比较。真要混合用,得手动加运算符数组结构。
比如查「状态为1且用户名含 admin」,不能只写字符串拼接,得这样:
['status' => 1, 'username' => ['like', '%admin%']]
常见错误是把 ['in', [1,2,3]] 写成 ['in', '1,2,3'] —— 后者会被当字符串处理,查不到数据。
-
['>', 10]和['gt', 10]等价,但前者更直觉;后者在旧版 TP6 中兼容性略好 - 多个字段都用
IN时,别共用一个键名,例如['id' => ['in', $ids], 'category_id' => ['in', $cats]] - 空数组传给
where不报错但会清空条件,调试时注意检查变量是否为空
闭包查询里写 where 容易搞混作用域和执行时机
闭包本质是延迟执行的查询构建器,不是“把 SQL 字符串塞进去”。很多人以为闭包里能直接用 PHP 变量拼 SQL,结果报错或被注入。
正确姿势是把闭包当第二个参数传给 where,它接收一个 $query 实例:
UserModel::where(function ($query) use ($keyword) {
$query->where('name', 'like', "%{$keyword}%")
->whereOr('email', 'like', "%{$keyword}%");
})->select();
关键点:闭包内必须调用 $query->where(),不能写 where('...')(那是静态方法,作用域不对)。
- 闭包里不能用
$this,除非显式use ($this),但不推荐——模型实例在闭包中不可靠 -
whereOr在闭包里才安全;全局用whereOr会污染后续条件 - TP6.1+ 支持在闭包里链式调用
whereTime、whereNull等,但老版本需转成where('field', 'exp', 'IS NULL')
混合使用数组 + 闭包时,顺序决定最终 SQL 逻辑
ThinkPHP 拼接条件时按调用顺序合并,不是按“数组优先/闭包优先”自动归类。先写 where($arr) 再写 where($closure),SQL 就是 AND ( ... );反过来就是 ( ... ) AND ...,括号位置不同,语义可能翻车。
比如要查「已启用 AND(是 VIP OR 有优惠券)」,必须:
->where(['status' => 1])
->where(function ($q) {
$q->where('is_vip', 1)->whereOr('coupon_id', '>', 0);
})
如果颠倒顺序,闭包外的条件会被包进括号里,变成 (status = 1 AND is_vip = 1) OR coupon_id > 0,结果完全不对。
- 所有
where调用都是追加,没有“覆盖”概念;重复字段会以后一次为准 -
whereRaw插入的原生片段不会被转义,务必自己过滤$keyword,别信闭包能帮你防注入 - TP6.0 开始支持
where(fn($q) => ...)简写,但 IDE 提示弱,建议显式写function ($q)避免混淆
复杂条件动态组装时,别硬塞空条件进 where 数组
用户搜索页常根据参数存在与否加条件,直接 if ($name) $where['name'] = ['like', "%$name%"] 看似省事,但一旦 $name 是 0 或 '',条件就误入——PHP 的松散判断会让空字符串也进数组。
更稳妥的是用 where 链式 + 条件判断,或者用 array_filter 清洗:
$where = array_filter([
$status ? ['status' => $status] : null,
$keyword ? ['name' => ['like', "%{$keyword}%"]] : null,
], function ($v) { return $v !== null; });
但注意:array_filter 默认过滤 falsy 值,0、false、null 全被干掉,所以状态值为 0 时得单独判断。
- TP6.2+ 提供
when方法,比手写 if 更清晰:->when($keyword, function ($q, $k) { $q->where('name', 'like', "%{$k}%"); }) - 闭包里调用
when也有效,适合分段控制子条件 - 动态条件多的时候,建议封装成独立方法,避免主逻辑堆满
if-where判断
最麻烦的其实是时间范围 + 多字段模糊 + 分类树联动,这种组合下,闭包嵌套两层、where 混用数组和表达式,括号层级很容易手抖写错。上线前一定拿真实参数跑一遍 SQL 日志看生成的语句。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











