Laravel使用Spatie时如何按角色分类分组显示权限列表
问题根源
当前使用左连接查询得到的是扁平化结构的结果集,每条权限记录都会携带对应分类的名称,遍历单条数据时每次都输出分类标题,自然会出现重复渲染分类名的问题。
修复步骤
1. 完善模型关联
在RoleCategory模型中定义和权限表的一对多关联:
// app/Models/RoleCategory.php public function permissions() { return $this->hasMany(\Spatie\Permission\Models\Permission::class, 'role_category_id'); }
2. 调整控制器查询逻辑
替换原来的左连接查询,改用Eloquent预加载关联的权限数据,同时修正原代码里的拼写错误(RoleCatgory拼写错误、Leftjoin写法不符合规范):
// 控制器方法内 $categories = RoleCategory::with('permissions')->get(); // 提前获取当前角色已有的权限ID数组,根据你实际的业务逻辑调整$role的获取方式 $rolePermissions = $role->permissions->pluck('id')->toArray(); return view('你的视图文件路径', compact('categories', 'rolePermissions'));
3. 重构Blade模板渲染逻辑
改用两层循环结构:外层遍历角色分类,仅输出一次分类标题;内层遍历当前分类下的所有权限,渲染复选框,从根源避免标题重复。同时修复原模板里复选框ID重复的bug:
@foreach($categories as $category) <h3>{{ $category->category_name }}</h3> <div class="row"> @foreach($category->permissions as $permission) @php $checked = in_array($permission->id, $rolePermissions) ? 'checked' : '' @endphp <div class="col-md-4 mb-2"> <input type="checkbox" class="form-check-input" id="permission-{{ $permission->id }}" name="permission[]" {{ $checked }} value="{{ $permission->id }}" > <label class="form-check-label" for="permission-{{ $permission->id }}"> {{ $permission->name }} </label> </div> @endforeach </div> @endforeach
额外说明:原模板中所有复选框和label的
id/for属性都写死为exampleCheck,不符合HTML规范,会导致点击任意label都只能选中第一个复选框,上述代码已经改为用权限ID拼接唯一标识的写法,可直接使用。
内容的提问来源于stack exchange,提问作者Ahil Khan
相关产品推荐
相关产品推荐

