数据库级联删除需在迁移中用cascadeondelete()配置外键,确保子表字段非nullable;eloquent事件删除则通过booted()监听deleted事件,用orders()->delete()高效物理删或orders->each->delete()触发事件;混合策略兼顾数据一致与业务逻辑。

在Laravel中执行嵌套查询删除时,父模型被删但子模型残留导致外键悬空、后续查询报错或数据不一致,必须明确区分数据库级联与Eloquent行为边界。
用数据库外键实现物理级联删除
第一步:在迁移文件中为子表外键添加 cascadeOnDelete()。
第二步:确保子表外键字段(如 user_id)不是 unsignedBigInteger 且未设为 nullable() —— 【若字段允许 NULL,MySQL 将拒绝 cascade 约束】。
第三步:运行 php artisan migrate。此时即使使用查询构建器批量删除(User::where('status', 'inactive')->delete()),数据库也会自动清理所有关联子记录,且不触发 Eloquent 事件。
用 Eloquent 事件手动处理嵌套关联删除
当子模型需触发 deleting 事件(如删除关联文件、同步缓存、写审计日志),不能依赖数据库级联,必须走 Eloquent 生命周期。
方法一:在父模型的 booted() 中监听 deleted 事件并链式调用子关系删除:
$model->orders()->delete(); —— 这条语句直接发 DELETE SQL,不加载模型实例,性能好;但注意它不会触发 Order::deleting 事件。
Laravel 13.2.0 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
方法二:先获取子模型集合,再逐个调用 delete():
$model->orders->each->delete(); —— 这会触发每个 Order 实例的 deleting 和 deleted 事件,适合有清理逻辑的场景;但内存占用高,不适用于上千条记录。
⚠️ 注意:若父模型启用软删除,$model->orders()->delete() 仍会物理删除子模型(除非子模型也启用软删除且你显式调用 forceDelete())。
混合策略:外键 + Eloquent 事件兜底
先配置数据库 cascadeOnDelete() 保证数据一致性底线,再在父模型中补充事件监听,仅处理非数据库职责(如删 OSS 文件、清 Redis 缓存)。
在迁移中定义外键时,同时保留 Eloquent 关系方法名与数据库字段名严格一致(如 orders() 对应 orders.user_id),否则 cascadeOnDelete() 生效但 Eloquent 预加载或事件绑定可能失效。
这一步操作起来很简单,直接把外键约束和事件监听写进同一张迁移文件即可,无需额外服务类或 Trait。
执行 php artisan migrate:fresh --seed 验证级联是否生效:插入一条父记录及多条子记录 → 删除父记录 → 检查子表是否为空。










