如何解决两个一对一关联模型软删除时的循环触发问题
问题原因
双向关联的模型事件互相触发导致无限递归:删除Owner时触发事件删除关联Car,Car的删除事件又会尝试删除关联Owner,反复调用最终导致程序卡死。
解决方案
在执行关联模型的删除/恢复操作前,先判断关联模型是否已经处于对应状态,仅当状态不匹配时才执行操作,避免重复触发事件。
调整后 Owner 模型代码
文件路径:App/Models/Owner
protected static function booted() { static::deleted(function ($owner) { $car = $owner->car()->withTrashed()->first(); // 仅当关联Car存在且未被软删除时才执行删除 if ($car && !$car->trashed()) { $car->delete(); } }); static::restored(function ($owner) { $car = $owner->car()->withTrashed()->first(); // 仅当关联Car存在且处于软删除状态时才执行恢复 if ($car && $car->trashed()) { $car->restore(); } }); }
以上代码兼容所有支持Laravel软删除的PHP版本,如果使用PHP8及以上版本,可以用?->空安全运算符简化判断逻辑。
调整后 Car 模型代码
文件路径:App/Models/Car
protected static function booted() { static::deleted(function ($car) { $owner = $car->owner()->withTrashed()->first(); // 仅当关联Owner存在且未被软删除时才执行删除 if ($owner && !$owner->trashed()) { $owner->delete(); } }); static::restored(function ($car) { $owner = $car->owner()->withTrashed()->first(); // 仅当关联Owner存在且处于软删除状态时才执行恢复 if ($owner && $owner->trashed()) { $owner->restore(); } }); }
可选轻量化方案
如果不需要触发关联模型的删除/恢复事件,也可以直接调用关联构造器的操作方法,跳过模型事件触发,从根源避免循环:
// 直接删除关联Car,不触发Car的模型事件 $owner->car()->delete(); // 直接恢复关联Car,不触发Car的模型事件 $owner->car()->withTrashed()->restore();
内容的提问来源于stack exchange,提问作者Rory
相关产品推荐
相关产品推荐

