Laravel表单提交可获取新值但数据库更新失败问题
问题原因
这个问题是两个典型的Laravel Eloquent使用错误叠加导致的:
- 模型未配置自定义主键
你的projects表主键字段是id_project,并非Laravel默认约定的id。如果不在模型中显式声明主键配置,Eloquent执行save()方法时会默认用id作为匹配条件查找记录,根本找不到对应数据行,自然无法完成更新。 - 请求参数取值不符合预期
你通过dd($request)看到请求体里有提交值,不代表$request->name这种动态属性取法能拿到正确的新值:- 如果表单字段用了数组命名(比如
name="project[name]"),直接取$request->name会得到null - 如果是PUT/PATCH请求、参数存在特殊格式,动态属性取值可能匹配到路由参数或者其他默认值,拿到的是和数据库原值一致的旧值
你写死固定字符串能更新成功,已经排除了数据库权限、SQL语法、路由绑定的问题,问题核心就是传入更新逻辑的动态请求值和你预期的新值不一致。如果传入的值和数据库原有值完全相同,Eloquent会自动跳过更新执行,表现出来就是“数据没变化”。
- 如果表单字段用了数组命名(比如
修复方案
- 第一步:修正Project模型配置
在app/Models/Project.php模型文件中添加如下配置,声明自定义主键,同时配置批量赋值白名单:class Project extends Model { // 声明自定义主键字段名 protected $primaryKey = 'id_project'; // 如果主键不是自增类型,添加以下配置 // public $incrementing = false; // 如果主键类型不是整数,添加以下配置 // protected $keyType = 'string'; // 配置批量赋值白名单,支持直接调用update方法批量写入 protected $fillable = [ 'name', 'country_id', 'currency_id', 'timezone_id', 'website' ]; } - 第二步:修正请求参数取值逻辑
不要依赖$request->name这类动态属性取值,改用input()方法明确获取表单参数,同时建议加上参数验证,避免非法值传入:public function update(Request $request, $id) { // 验证传入参数格式 $validated = $request->validate([ 'name' => 'required|string|max:255', 'country' => 'required|integer', 'currency' => 'required|integer', 'timezone' => 'required|integer', 'website' => 'required|string' ]); // 用firstOrFail找不到记录时直接返回404,避免空对象报错 $project = Project::where('id_project', $id)->firstOrFail(); $project->name = $validated['name']; $project->country_id = $validated['country']; $project->currency_id = $validated['currency']; $project->timezone_id = $validated['timezone']; $project->website = $validated['website']; $project->save(); return response()->json($project, 200); }配置完
$fillable后也可以简化为批量更新写法:$project = Project::where('id_project', $id)->firstOrFail(); $project->update([ 'name' => $request->input('name'), 'country_id' => $request->input('country'), 'currency_id' => $request->input('currency'), 'timezone_id' => $request->input('timezone'), 'website' => $request->input('website') ]); - 第三步:异常排查
如果修改后还是无法更新,在更新逻辑前单独打印目标参数值,不要只打印整个Request对象:
如果打印结果为null或者和数据库原值一致,就去检查表单的// 单独打印name字段的实际取值 dd($request->input('name'));name属性是否拼写正确、是否存在嵌套数组结构、请求是否正常携带了CSRF令牌。
内容的提问来源于stack exchange,提问作者Shibbir
相关产品推荐
相关产品推荐

