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

Laravel:booted函数中save触发死循环,求slug正确存储方案

解决Laravel中saved事件调用save()导致无限循环的Slug生成问题

你遇到的问题核心是无限循环:saved事件会在模型创建/更新完成后触发,而你在回调里调用$discussion->save(),会再次触发saved事件,反复执行下去最终导致服务器资源耗尽卡死。

下面是几种可行的解决方案:

方案1:使用updateQuietly()(推荐,Laravel 8.42+)

updateQuietly()方法会直接更新数据库,不会触发任何模型事件,完美避免循环。同时增加判断逻辑,只有当slug确实需要更新时才执行操作,减少不必要的数据库请求:

protected static function booted(): void
{   
    static::saved(function (Discussion $discussion) {
        $newSlug = Str::slug($discussion->subject, '-') . '-' . $discussion->id;
        // 仅当slug发生变化时才更新
        if ($discussion->slug !== $newSlug) {
            $discussion->updateQuietly(['slug' => $newSlug]);
        }
    }); 

    static::deleting(function (Discussion $discussion) {
        $discussion->groups()->detach();
        $discussion->registrations()->delete();
    }); 
}

方案2:使用saveQuietly()或临时禁用事件(兼容低版本Laravel)

如果你的Laravel版本低于8.42,可以用saveQuietly()(Laravel 8+支持),或者用withoutEvents()临时禁用事件:

static::saved(function (Discussion $discussion) {
    $newSlug = Str::slug($discussion->subject, '-') . '-' . $discussion->id;
    if ($discussion->slug !== $newSlug) {
        $discussion->slug = $newSlug;
        // 方法A:使用saveQuietly
        $discussion->saveQuietly();

        // 方法B:临时禁用事件包裹操作
        // $discussion->withoutEvents(function () use ($discussion) {
        //     $discussion->save();
        // });
    }
});

方案3:拆分事件为created和updated(更精准控制)

既然创建时需要ID,created事件是创建完成后触发(此时已有ID),更新时监听updated事件,分开处理逻辑:

protected static function booted(): void
{   
    static::created(function (Discussion $discussion) {
        $discussion->slug = Str::slug($discussion->subject, '-') . '-' . $discussion->id;
        $discussion->saveQuietly();
    });

    static::updated(function (Discussion $discussion) {
        // 仅当subject字段修改时,才更新slug
        if ($discussion->isDirty('subject')) {
            $newSlug = Str::slug($discussion->subject, '-') . '-' . $discussion->id;
            if ($discussion->slug !== $newSlug) {
                $discussion->updateQuietly(['slug' => $newSlug]);
            }
        }
    });

    static::deleting(function (Discussion $discussion) {
        $discussion->groups()->detach();
        $discussion->registrations()->delete();
    }); 
}

内容的提问来源于stack exchange,提问作者Duddy67

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:42:43