Laravel用户更新时如何在Request验证规则中获取用户ID
核心问题根因
你遇到的报错和业务逻辑异常,本质来自三个代码硬伤:
- 自定义Request类中获取用户ID的方式完全错误
- 验证规则的数组写法语法错误,很多规则实际没有生效
- 邮箱唯一性校验没有排除当前编辑用户的自身记录,导致系统重复检测用户自己的邮箱
具体修正方案
1. 正确从Request中获取路由传递的用户ID
你的编辑提交路由定义为POST users/edit/{id},这个{id}参数是直接挂载在路由实例上的,根本不需要从不存在的模型属性里取值。
在自定义Request类中,直接用$this->route('参数名')就能拿到路由携带的id值。之前写的$this->users->id会触发「Trying to get property 'id' of non-object」报错,是因为Request实例本身没有名为users的模型属性——之前混淆了自定义Request类和用户模型类,才会写出访问不存在属性的代码。
2. 修正验证规则的语法错误
Laravel的验证规则数组,结构必须遵循「字段名 => 该字段对应的所有规则组成的数组/字符串」的格式。你之前的写法把规则散到了数组顶层,相当于把规则名当成了数组的独立键,实际根本没有绑定到对应字段上,所有后续规则都是失效的。
3. 调整邮箱唯一校验的逻辑
做更新操作的邮箱唯一校验时,必须排除当前正在编辑的用户ID对应的记录。否则就算用户原样提交自己当前的邮箱,系统检测到这个邮箱在表里存在,就会判定为「邮箱已被其他用户占用」,触发错误提示。
修正后的参考代码
自定义Request类
public function rules() { // 直接从路由参数拿到当前要编辑的用户ID,不会触发非对象报错 $editUserId = $this->route('id'); return [ 'name' => ['required', 'string', 'max:255'], // 唯一规则排除当前用户自身,解决不修改邮箱就提示占用的问题 'email' => [ 'sometimes', 'required', 'string', 'email', 'max:255', "unique:users,email,{$editUserId}" ], // 改成可选必填,允许用户不修改密码 'password' => ['sometimes', 'required', 'string', 'min:8', 'confirmed'], 'role' => ['required', 'string'], ]; }
控制器代码
// 注入自定义Request类,不要把Request类和用户模型类混淆 public function edit(UpdateUserRequest $request, $id) { $targetUser = User::whereId($id)->firstOrFail(); $targetUser->name = $request->get('name'); $targetUser->email = $request->get('email'); // 只有用户实际提交了新密码时才更新,避免强制每次编辑都要重输密码 if ($request->filled('password')) { $targetUser->password = Hash::make($request->get('password')); } $targetUser->role = $request->get('role'); $targetUser->save(); $request->session()->forget('editvalue'); $userList = User::paginate(4); return view('pages.auth.user_list', compact('userList'))->with('status','用户信息更新成功'); }
额外注意点
- 如果你希望用户完全不提交邮箱字段时不触发邮箱校验,现在的
sometimes规则配置是生效的:只有请求里传了email值,才会跑后续的格式和唯一校验。 - 之前控制器里的
$users->update()在配置了模型可填充字段的前提下是可以用的,但如果有需要单独处理的字段(比如上面的密码条件判断),用save()会更灵活。
内容的提问来源于stack exchange,提问作者user11082357
相关产品推荐
相关产品推荐

