You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决两个一对一关联模型软删除时的循环触发问题

问题原因

双向关联的模型事件互相触发导致无限递归:删除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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 13:06:08