You need to enable JavaScript to run this app. Laravel Observer updated事件触发循环 引发SQLSTATE[22001]字段过长错误
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Observer updated事件触发循环 引发SQLSTATE[22001]字段过长错误

触发循环的核心逻辑

无限递归的链路非常清晰:

  • 控制器内首次执行$species->save(),完成数据库写入后,自动触发Species模型的updated事件
  • 进入观察者的updated方法后,代码修改name字段后再次调用$species->save()
  • 这次写入会再次触发updated事件,重复执行「修改name -> 保存」的流程,形成无限循环
  • 循环持续到name字段的字符串长度超过数据库定义的列上限,抛出SQLSTATE[22001]: 字符串数据,右截断:1406 列存储数据过长错误
可直接落地的修复方案
  1. 直接打断循环链路
    把观察者方法内的普通save()替换为saveQuietly(),该方法执行数据库写入时不会触发任何模型事件,从根源上切断递归触发的路径。同时要增加重复拼接校验,哪怕循环被打断,也避免多次触发更新时反复给name叠加ID后缀。
    修正后的观察者代码示例:

    public function updated(Species $species)
    {
        // 校验是否已经追加过对应ID,避免重复拼接
        if (!str_contains($species->name, " - {$species->id}")) {
            $species->name = "{$species->name} - {$species->id}";
            // 静默写入,不触发后续模型事件
            $species->saveQuietly();
        }
    }
    
  2. 从流程设计上规避重复触发
    完全不需要依赖观察者做这个逻辑的话,直接在控制器的更新流程里拼接带ID的名称,在首次save之前完成字段赋值,彻底绕开事件触发的问题:

    public function update(Request $request, Species $species)
    {
        $species->name = $request->name . ' - ' . $species->id;
        $species->sort = $request->sort;
    
        $species->save();
    
        $updatedSpecies = new SpeciesResource($species);
    
        return response()->json(compact('updatedSpecies'), 200);
    }
    
  3. 适配观察者的正确钩子时机
    如果坚持要用观察者实现这个逻辑,不要监听updated(更新完成后触发)事件,改成监听saving(执行数据库写入前触发)事件,整个流程只执行一次数据库写入,完全不会出现循环:

    /**
     * 处理species保存前的逻辑
     * @param \App\Species $species
     * @return void
     */
    public function saving(Species $species)
    {
        // 避免重复拼接ID后缀
        if (!str_contains($species->name, " - {$species->id}")) {
            $species->name = "{$species->name} - {$species->id}";
        }
    }
    
避坑提醒
  • 只要是在updated、saved这类「数据库写入完成后」触发的模型钩子里,直接调用普通save()方法、且没有做事件拦截,必然会触发同类型的下一轮钩子,形成无限递归
  • 提前给数据库中name字段的长度预留冗余空间,避免后续逻辑调整时偶发的字符串截断错误

内容的提问来源于stack exchange,提问作者cyber-leech

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 22:54:02