不会。Laravel 的 delete() 默认只删当前模型,不级联删除关联记录,需手动处理如 $user->profile?->delete() 或 $user->profile()->delete(),并配合数据库外键 CASCADE 与 Eloquent 事件确保一致性。

delete() 会自动删关联记录吗?
不会。Laravel 的 delete() 默认只删当前模型,哪怕你定义了 belongsTo() 或 hasOne() 关系,也不会级联删除。这是 Laravel 的默认行为,不是 bug,是设计选择——避免误删。
常见错误现象:User::find(1)->delete() 执行后,Profile 表里对应记录还在,导致外键悬空或后续查询报错。
- 必须显式处理关联数据,不能依赖 ORM 自动清理
- 如果数据库外键设置了
ON DELETE CASCADE,物理删除由 MySQL/PostgreSQL 完成,但 Laravel 模型事件(如deleting)不会触发 - 想兼顾数据库约束 + Eloquent 事件,得手动删 + 确保外键配置一致
用 detach() 还是 delete()?
detach() 是针对多对多关系的方法,不适用于一对一。对 hasOne 或 belongsTo,它根本不存在,调用会报 Method detach does not exist 错误。
正确做法只有两种:
- 先取关联模型,再调用它的
delete():$user->profile?->delete() - 用关系方法的
delete()(仅限hasOne):$user->profile()->delete()—— 这会直接发 DELETE SQL,不加载模型,性能略好 - 注意:
$user->profile是懒加载,可能为null;$user->profile()是关系实例,可链式调用,但不能访问属性
如何在 deleting 事件里安全删关联?
在模型的 deleting 事件中删关联最常用,但要注意执行顺序和空值风险。
示例(User.php):
protected static function booted()
{
static::deleting(function ($user) {
$user->profile?->delete();
});
}
- 务必用
?->避免Call to a member function delete() on null - 不要在
deleted事件里删关联,因为此时主模型已删,外键可能已被清空或约束拒绝操作 - 如果关联表有软删除,
$user->profile?->delete()会转为软删;硬删需用$user->profile?->forceDelete()
外键设了 CASCADE,还要写代码吗?
要。即使数据库层能自动删,Eloquent 不知道这事发生了,所以 deleting / deleted 事件不会触发,监听日志、清理缓存、发通知等逻辑就丢了。
- 推荐组合:数据库外键 + Eloquent 事件,两者都配,且行为一致
- 检查迁移里是否用了
->onDelete('cascade'),比如:$table->foreignId('user_id')->constrained()->onDelete('cascade') - 如果只靠数据库 cascade,测试时容易漏掉业务逻辑副作用,上线后出问题难定位
真正麻烦的从来不是“怎么删”,而是删完之后谁来保证一致性——事件没触发、缓存没清、第三方没通知,这些点比 SQL 多一条 JOIN 更容易翻车。


















