Eloquent更新数据行返回成功但数据库无变更问题求助
这种情况我之前踩过好几次坑!Eloquent返回1(也就是true)但数据库没动静,大概率是下面这些细节没处理到位,咱们一个个排查:
模型可填充字段(fillable)未配置
Eloquent默认会保护批量赋值操作,如果你用update()传数组或者fill()方法赋值,但模型里的$fillable数组没包含要更新的字段,这些字段会被静默跳过——不会报错,数据库自然也不会有变化。
比如你要更新nombre和descripcion字段,模型里得这么配置:class PublicoObjetivo extends Model { protected $fillable = ['nombre', 'descripcion']; // 或者如果不想限制批量赋值(生产环境谨慎使用): // protected $guarded = []; }主键配置不匹配或查询条件有误
如果你的模型主键不是默认的id(比如是codigo),但没在模型里指定$primaryKey,Eloquent会用默认的id去查找数据,可能刚好匹配到了某行,但不是你要更新的那一行;或者你查询时用了错误的条件,比如where('id', $wrongId),但巧合有一行符合条件,更新的值又和原数据完全一致,数据库就不会有变化。
检查模型的主键配置:protected $primaryKey = 'codigo'; // 如果主键是字符串类型,还要加: protected $keyType = 'string';更新操作未真正执行
如果你是先查询模型实例、修改属性,但忘了调用save()方法,那数据库肯定不会变。比如:// 错误示例:只修改属性,没保存 $model = PublicoObjetivo::find($id); $model->nombre = '新名称'; return 1; // 误以为操作成功,但实际没保存 // 正确写法 $model = PublicoObjetivo::find($id); $model->nombre = '新名称'; return $model->save(); // 调用save()才会持久化到数据库字段名拼写/大小写不匹配
比如数据库里的字段是descripcion,但你代码里写成了description;或者在区分大小写的系统(比如Linux)上,数据库字段是Descripcion,你代码里用小写descripcion,这时候Eloquent不会报错,但更新的是不存在的字段,数据库自然没变化。
直接核对数据库字段名和代码里的字段名,确保完全一致。事务未提交
如果你的更新逻辑包裹在事务里,但只执行了更新,没调用commit(),事务会自动回滚,数据库就不会保留修改。比如:DB::beginTransaction(); try { $affected = PublicoObjetivo::where('id', $id)->update($data); // 这里漏掉了DB::commit(); return $affected; } catch (\Exception $e) { DB::rollBack(); throw $e; }这种情况
update()会返回1,但事务没提交,数据库毫无变化。软删除模型的干扰
如果你的模型使用了软删除(引入了SoftDeletestrait),默认情况下update()不会操作已被软删除的行。如果你的目标行已经被软删除,需要加上withTrashed()才能更新:PublicoObjetivo::withTrashed()->where('id', $id)->update($data);
终极排查技巧:查看实际执行的SQL
如果上面的点都排查了还是没解决,开启Eloquent的查询日志,看看实际生成的SQL语句是什么,一眼就能找到问题:
DB::enableQueryLog(); // 执行你的更新代码 dd(DB::getQueryLog());
比如你会看到生成的SQL里字段名不对,或者条件错误,或者要更新的值和原数据完全一致,数据库就不会标记为修改。
内容的提问来源于stack exchange,提问作者Sebastian Linux

