ThinkPHP 5.1+ 废弃数组写法因无法表达嵌套逻辑、动态条件及复杂SQL,解析开销大且易出错;v5.1.37起触发E_USER_DEPRECATED警告,v6.x彻底移除。
ThinkPHP 5.1+ 中
数组写法为什么被标记为废弃
因为数组方式(如
)无法表达嵌套逻辑、动态条件拼接和复杂 SQL 结构,框架底层必须做大量字符串解析和映射,既慢又容易出错。官方从 v5.1.37 开始对这类写法抛出
警告,v6.x 已彻底移除支持。
常见错误现象:
;或升级后查询直接报错、条件丢失、SQL 生成异常。
动态构建条件时,数组写法很难安全处理空值、
或未定义键
含
、嵌套
、子查询的场景,数组根本无法表达
不同数据库驱动对数组字段顺序、嵌套层级的兼容性不一致,尤其在 PostgreSQL 或 SQL Server 上更易翻车
用闭包替代数组写法的实操要点
闭包是 ThinkPHP 推荐的标准写法,它把条件构造逻辑交还给开发者,框架只负责拼接 SQL 片段,性能更高、语义更清晰、调试更直观。
典型写法:
立即学习
“
PHP免费学习笔记(深入)
”;
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
所有原始
方法(
、
、
等)在闭包内都可直接调用
动态条件推荐用
判断包裹,避免生成多余 SQL:例如
多级嵌套用多个闭包:外层
,内层用
或再套
闭包实现括号分组
注意变量作用域:闭包内访问外部变量需用
显式引入,否则会报
迁移时最容易踩的三个坑
不是简单把数组塞进闭包就能跑通,结构差异会导致逻辑反转或 SQL 错误。
数组中的条件不能直接平铺
:原写法
必须改写为
或用闭包 +
空数组或全 null 条件不会被自动忽略
:闭包里要自己判断,比如
,否则可能生成
导致报错
时间范围查询别硬套
:数组写法中
对应闭包写法是
,不是
—— 后者会被当作文本匹配处理
闭包写法对性能和可维护性的真实影响
闭包本身没有运行时开销,反而因跳过数组解析阶段,实际执行更快;更重要的是它让条件逻辑变得「可读、可断点、可复用」。
调试时可在闭包内加
直接看最终生成的查询条件数组
复杂查询可抽成独立方法,例如
,提升复用率
团队协作时,新人一眼能看懂条件组合逻辑,不用猜数组键名含义(比如
、
这类历史遗留字段)
注意:过度嵌套闭包(三层以上)会让代码变难读,建议拆分成带语义的方法或提前计算好中间条件变量
最常被忽略的是闭包中对
和空字符串的处理逻辑——它们在 SQL 中行为完全不同,但数组写法曾掩盖了这个问题;现在必须显式决定用
、
还是
。
where['status' => 1, 'type' => ['in', [1,2]]]E_USER_DEPRECATEDDeprecated: Array where condition is deprecatednullORAND/OR->where(function ($query) { $query->where('status', 1)->where('type', 'in', [1,2]); })wherewherewhereLikewhereBetweenifif (!empty($search)) { $query->where('title', 'like', "%{$search}%"); }andorwhereuse ($var)Undefined variableOR['name' => 'a', 'OR' => ['email' => 'b']]$query->where('name', 'a')->whereOr(['email' => 'b'])whereOrif ($ids) { $query->where('id', 'in', $ids); }WHERE id IN ()between['create_time' => ['between', [$start, $end]]]$query->whereBetween('create_time', [$start, $end])where('create_time', 'between', [...])dump($query->getOptions())->where($this->buildSearchCondition($params))_logic_complexNULLisNull()isEmpty()where('field', '')