如何在Laravel FormRequest中按角色限制模型属性编辑权限?
Laravel/Backpack 按角色过滤可编辑字段的后端实现
针对你需要按用户角色限制模型属性写入权限、静默过滤非法字段的需求,用自定义FormRequest就能优雅实现,核心思路是动态生成允许字段列表 + 在验证前过滤请求数据,具体实现如下:
创建对应模型的FormRequest
以Client模型的更新请求为例,生成ClientUpdateRequest(新增请求逻辑一致,可复用):php artisan make:request ClientUpdateRequest定义角色对应的允许字段
在FormRequest中添加方法,根据当前用户角色返回允许编辑的字段数组:protected function getAllowedFields() { $user = auth()->user(); // 普通用户可编辑的基础字段 $fields = ['name', 'phone']; // 管理员额外可编辑active字段 if ($user->hasRole('admin')) { $fields[] = 'active'; } // 超级管理员额外可编辑viewCount字段 if ($user->hasRole('super_admin')) { $fields[] = 'viewCount'; } return $fields; }验证前过滤请求数据
利用FormRequest的prepareForValidation方法,在验证开始前自动移除请求中不属于允许列表的字段:protected function prepareForValidation() { // 只保留合法字段,静默丢弃恶意传入的属性 $this->merge( $this->only($this->getAllowedFields()) ); }动态生成验证规则
根据允许的字段生成对应验证规则,确保只校验有权限编辑的字段:public function rules() { $rules = [ 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20', ]; $user = auth()->user(); if ($user->hasRole('admin')) { $rules['active'] = 'boolean'; } if ($user->hasRole('super_admin')) { $rules['viewCount'] = 'integer|min:0'; } return $rules; }在Backpack CrudController中使用FormRequest
修改ClientCrudController的update方法,指定使用自定义的FormRequest:public function update(ClientUpdateRequest $request) { // 此处的$request已被过滤为合法数据 return $this->crud->update($request->id, $request->validated()); }优化:复用逻辑到基类
如果多个模型都需要按角色过滤字段,可以抽象一个基类统一处理:abstract class BaseRoleRestrictedRequest extends FormRequest { abstract protected function getBaseFields(); abstract protected function getAdminExtraFields(); abstract protected function getSuperAdminExtraFields(); protected function getAllowedFields() { $fields = $this->getBaseFields(); $user = auth()->user(); if ($user->hasRole('admin')) { $fields = array_merge($fields, $this->getAdminExtraFields()); } if ($user->hasRole('super_admin')) { $fields = array_merge($fields, $this->getSuperAdminExtraFields()); } return $fields; } protected function prepareForValidation() { $this->merge($this->only($this->getAllowedFields())); } }后续模型的FormRequest只需继承该基类并实现对应字段方法即可,代码更简洁。
内容的提问来源于stack exchange,提问作者Pekka
相关产品推荐
相关产品推荐

