Model::destroy()只接受主键值或闭包,不支持链式调用或非主键条件;正确做法是先查ID再销毁,或直接用Db::delete()绕过模型层执行原生删除。
Model::destroy() 只认主键,非主键字段删不了
很多人写
,直接报错:Call to undefined method destroy()。因为
是静态方法,不接受查询构造器链式调用,只接收主键值(单个 ID、ID 数组、或闭包条件)。它内部会先查 ID,再删——但这个“查 ID”只支持按主键查,不支持任意字段。
常见错误现象:
看似合理,实际会被当成主键值去查,导致 SQL 错误或删错数据。
正确做法是显式提取 ID:
,再
如果模型没定义主键(比如视图表),
会失效,必须改用
会触发模型的
/
事件,适合需要业务钩子的场景
Db::delete() 不走模型逻辑,但最快最可控
当你要删大量数据、且不需要模型事件、验证、软删除逻辑时,
是最直接的选择。它生成原生 DELETE 语句,绕过模型层,性能高,也不受软删除配置影响。
注意:它不调用任何模型方法,所以
字段不会被自动写入,也不会触发事件。如果你启用了软删除但又想真删,这是唯一可靠方式。
立即学习
“
PHP免费学习笔记(深入)
”;
支持
条件:
支持复合条件:
返回值是影响行数(int),可用于判断是否真有数据被删
软删除批量操作必须用 destroy(true),不能靠 where()->delete()
启用
trait 后,
依然会走软删逻辑——但这是假的:它只对模型实例有效,对查询构造器无效,实际执行的是硬删(除非你重写了 delete 方法)。
真正安全的软删批量操作只有一种:
。第二个参数
表示「强制软删」,即使传的是 ID 列表也会统一打上
标记。
不加
:默认行为是硬删(如果模型没启用软删除)或按主键软删(如果启用)
要恢复数据,得先
查出,再逐条调用
是查询时用的,不影响删除动作本身
别信 batchDelete(),TP6 已移除,TP5 也极少用
网上有些教程提到
,这在 TP6 中根本不存在;TP5 虽有,但仅限于极老版本(
它的底层就是封装了一次
,和手写
没本质区别,反而多一层不可控封装。
TP5 中若存在,需确认框架版本 ≥ 5.0.18 且开启了数据库调试才可能暴露
TP6 完全删掉了该方法,调用会抛出
所有稳定、可维护的批量删逻辑,都应回归到
或
两条路径
真正麻烦的不是语法,而是软删和硬删混用时的边界判断——比如某个接口既要清理过期数据(硬删),又要归档异常用户(软删),这时候模型配置、调用方式、事务包裹,一个没对齐就丢数据。
UserModel::where('status', 0)->destroy()destroy()UserModel::destroy(['status' => 0])$ids = UserModel::where('status', 0)->column('id');UserModel::destroy($ids)destroy()Db::name('user')->where('status', 0)->delete()destroy()deletingdeletedDb::name('user')->where('status', 0)->delete()soft_deleteinDb::name('user')->where('id', 'in', [1,2,3])->delete()Db::name('user')->where('status', 0)->where('created_time', 'delete()SoftDeleteUserModel::where('status', 0)->delete()UserModel::destroy($ids, true)truedelete_timetrueUserModel::withTrashed()->where('status', 0)->select()$model->restore()withTrashed()Db::table('user')->batchDelete()DELETE ... IN (...)Db::delete()Call to undefined methoddestroy()Db::delete()