自定义UserCrudController致Laravel Backpack权限管理器角色/权限无法加载
问题描述
使用Laravel ^10、Backpack Pro ^1.6、Laravel-permission ^5.10及Laravel Backpack Permission Manager ^6.0,基于PermissionManager原生控制器自定义了UserCrudController,用于处理模型验证需求和列表额外列显示,遇到以下问题:
- 编辑用户时,角色UI正常加载,但原有角色值无法回显
- 修改角色后无法保存到数据库
- 列表页面中角色显示正常,且User模型已正确引入
CrudTrait和HasRoles - 使用原生UserCrudController时编辑功能正常,但因User表无
name字段导致验证失败
自定义UserCrudController代码:
<?php namespace App\Http\Controllers\Admin; use Backpack\CRUD\app\Http\Controllers\CrudController; use Backpack\PermissionManager\app\Http\Requests\UserStoreCrudRequest as StoreRequest; use App\Http\Requests\UserUpdateCrudRequest as UpdateRequest; use Illuminate\Support\Facades\Hash; /** * Class UserCrudController * @package App\Http\Controllers\Admin * @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud */ class UserCrudController extends CrudController { use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation; use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; } use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation { update as traitUpdate; } use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation; /** * Configure the CrudPanel object. Apply settings to all operations. * * @return void */ public function setup() { $this->crud->setModel(config('backpack.permissionmanager.models.user')); $this->crud->setEntityNameStrings( trans('backpack::permissionmanager.user'), trans('backpack::permissionmanager.users') ); $this->crud->setRoute(backpack_url('user')); } /** * Define what happens when the List operation is loaded. * * @see https://backpackforlaravel.com/docs/crud-operation-list-entries * @return void */ protected function setupListOperation() { $this->crud->addColumns([ [ 'name' => 'username', 'type' => 'text', ], [ 'name' => 'name', 'type' => 'text', 'value' => function ($entry) { return $entry->profileName(); }, 'searchLogic' => function ($query, $column, $searchTerm) { $query->orWhereHas('profile', function ($q) use ( $column, $searchTerm ) { $q->where('first_name', 'like', '%' . $searchTerm . '%') ->orWhere( 'last_name', 'like', '%' . $searchTerm . '%' ) ->orWhere( 'middle_name', 'like', '%' . $searchTerm . '%' ); }); }, ], [ 'name' => 'email', 'label' => trans('backpack::permissionmanager.email'), 'type' => 'email', ], [ // n-n relationship (with pivot table) 'label' => trans('backpack::permissionmanager.roles'), // Table column heading 'type' => 'select_multiple', 'name' => 'roles', // the method that defines the relationship in your Model 'entity' => 'roles', // the method that defines the relationship in your Model 'attribute' => 'name', // foreign key attribute that is shown to user 'model' => config('permission.models.role'), // foreign key model ], [ // n-n relationship (with pivot table) 'label' => trans( 'backpack::permissionmanager.extra_permissions' ), // Table column heading 'type' => 'select_multiple', 'name' => 'permissions', // the method that defines the relationship in your Model 'entity' => 'permissions', // the method that defines the relationship in your Model 'attribute' => 'name', // foreign key attribute that is shown to user 'model' => config('permission.models.permission'), // foreign key model ], ]); if (backpack_pro()) { // Role Filter $this->crud->addFilter( [ 'name' => 'role', 'type' => 'dropdown', 'label' => trans('backpack::permissionmanager.role'), ], config('permission.models.role') ::all() ->pluck('name', 'id') ->toArray(), function ($value) { // if the filter is active $this->crud->addClause('whereHas', 'roles', function ( $query ) use ($value) { $query->where('role_id', '=', $value); }); } ); // Extra Permission Filter $this->crud->addFilter( [ 'name' => 'permissions', 'type' => 'select2', 'label' => trans( 'backpack::permissionmanager.extra_permissions' ), ], config('permission.models.permission') ::all() ->pluck('name', 'id') ->toArray(), function ($value) { // if the filter is active $this->crud->addClause('whereHas', 'permissions', function ( $query ) use ($value) { $query->where('permission_id', '=', $value); }); } ); } } public function setupCreateOperation() { $this->addUserFields(); $this->crud->setValidation(StoreRequest::class); } public function setupUpdateOperation() { $this->addUserFields(); $this->crud->setValidation(UpdateRequest::class); } /** * Store a newly created resource in the database. * * @return \Illuminate\Http\RedirectResponse */ public function store() { $this->crud->setRequest($this->crud->validateRequest()); $this->crud->setRequest( $this->handlePasswordInput($this->crud->getRequest()) ); $this->crud->unsetValidation(); // validation has already been run return $this->traitStore(); } /** * Update the specified resource in the database. * * @return \Illuminate\Http\RedirectResponse */ public function update() { $this->crud->setRequest($this->crud->validateRequest()); $this->crud->setRequest( $this->handlePasswordInput($this->crud->getRequest()) ); $this->crud->unsetValidation(); // validation has already been run return $this->traitUpdate(); } /** * Handle password input fields. */ protected function handlePasswordInput($request) { // Remove fields not present on the user. $request->request->remove('password_confirmation'); $request->request->remove('roles_show'); $request->request->remove('permissions_show'); // Encrypt password if specified. if ($request->input('password')) { $request->request->set( 'password', Hash::make($request->input('password')) ); } else { $request->request->remove('password'); } return $request; } protected function addUserFields() { $this->crud->addFields([ [ 'name' => 'username', 'type' => 'text', ], [ 'name' => 'email', 'label' => trans('backpack::permissionmanager.email'), 'type' => 'email', ], [ 'name' => 'password', 'label' => trans('backpack::permissionmanager.password'), 'type' => 'password', ], [ 'name' => 'password_confirmation', 'label' => trans( 'backpack::permissionmanager.password_confirmation' ), 'type' => 'password', ], [ // two interconnected entities 'label' => trans( 'backpack::permissionmanager.user_role_permission' ), 'field_unique_name' => 'user_role_permission', 'type' => 'checklist_dependency', 'name' => 'roles,permissions', 'subfields' => [ 'primary' => [ 'label' => trans('backpack::permissionmanager.roles'), 'name' => 'roles', // the method that defines the relationship in your Model 'entity' => 'roles', // the method that defines the relationship in your Model 'entity_secondary' => 'permissions', // the method that defines the relationship in your Model 'attribute' => 'name', // foreign key attribute that is shown to user 'model' => config('permission.models.role'), // foreign key model 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?] 'number_columns' => 3, //can be 1,2,3,4,6 ], 'secondary' => [ 'label' => mb_ucfirst( trans( 'backpack::permissionmanager.permission_plural' ) ), 'name' => 'permissions', // the method that defines the relationship in your Model 'entity' => 'permissions', // the method that defines the relationship in your Model 'entity_primary' => 'roles', // the method that defines the relationship in your Model 'attribute' => 'name', // foreign key attribute that is shown to user 'model' => config('permission.models.permission'), // foreign key model 'pivot' => true, // on create&update, do you need to add/delete pivot table entries?] 'number_columns' => 3, //can be 1,2,3,4,6 ], ], ], ]); } }
解决方案
问题根源在于handlePasswordInput方法中移除了roles_show和permissions_show字段,这两个字段是checklist_dependency组件回显已有角色/权限的关键参数;同时更新逻辑中缺少角色和权限的同步处理。具体修复步骤:
恢复必要的回显字段
删除handlePasswordInput方法中的以下两行代码:$request->request->remove('roles_show'); $request->request->remove('permissions_show');补充角色和权限同步逻辑
修改update方法,在执行原生更新后手动同步角色和权限:public function update() { $this->crud->setRequest($this->crud->validateRequest()); $request = $this->handlePasswordInput($this->crud->getRequest()); $this->crud->setRequest($request); $this->crud->unsetValidation(); // 执行原生更新逻辑 $response = $this->traitUpdate(); // 同步角色和权限 $entry = $this->crud->getCurrentEntry(); if ($request->has('roles')) { $entry->syncRoles($request->input('roles')); } if ($request->has('permissions')) { $entry->syncPermissions($request->input('permissions')); } return $response; }修正验证规则
在自定义的UserUpdateCrudRequest中移除对name字段的验证要求,示例:// app/Http/Requests/UserUpdateCrudRequest.php public function rules() { return [ 'username' => 'required|string|max:255', 'email' => 'required|email|unique:users,email,'.$this->route('user'), // 移除name字段的验证规则 ]; }
内容的提问来源于stack exchange,提问作者waffl
相关产品推荐
相关产品推荐

