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

Laravel模型在try/catch中更新后保留错误值的原因咨询

问题描述

在Laravel中更新数据库数据时,deployment_id列是唯一约束列。当尝试用重复值更新该字段触发唯一约束错误后,在catch块中仅更新模型的inprogress和error字段,却再次触发相同的唯一约束错误。

简化代码如下:

public $defaultModel ;

function errorTest(){
    $this->defaultModel = $inprogress = Process::where('inprogress' , 1 )->first();
    try
    {
        $inprogress->update( [
            'deployment_id' => 666 ,
        ]);

    }
    catch (\Exception $exception)
    {
        $this->defaultModel->update([
            'inprogress' => 0  ,
            'error'=>'duplicate'
        ]);
    }
}

触发的SQL错误:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '666' for key 'process_deployment_id_unique'

排查发现错误来自catch块的更新操作:即使未在catch中修改deployment_id列,模型仍保留try块中设置的deployment_id=666值,导致再次触发唯一约束错误。仅通过重新从数据库拉取模型再更新才能解决:

$model = $this->defaultModel->fresh();
$model->update([
    'inprogress' => 0  ,
    'error'=>'duplicate'
]);
原因解释

Laravel的Eloquent模型是内存中的数据对象:当在try块调用$inprogress->update(['deployment_id' => 666])时,虽然数据库层面因唯一约束更新失败,但Eloquent已经将内存中模型实例的deployment_id属性修改为666。

进入catch块调用$this->defaultModel->update()时,Eloquent会基于内存中当前模型的所有属性生成更新语句——它会把已被修改为666的deployment_id也包含在更新字段里,自然再次触发唯一约束错误。

而fresh()方法会从数据库重新获取该模型的最新数据,覆盖内存中被修改过的属性,此时模型的deployment_id恢复为数据库里的原始值,再执行更新就不会携带重复的666值,也就不会触发约束错误了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 19:55:31