laravel-admin 菜单需绑定 spatie 权限并关联角色实现动态显示:菜单项设 'permission' 字段,用 givepermissionto() 分配权限,用户 assignrole() 绑定角色,渲染时通过 auth()->user()->can() 过滤,并确保 guard_name='admin' 一致。

要让 Laravel-Admin 的菜单真正按角色分组显示,不能只靠菜单配置文件写死结构,关键得把菜单项和权限(permission)挂钩,再通过角色(role)统一分配——这样不同角色登录后看到的菜单才自动不同。
菜单项必须绑定具体权限名
在菜单模型(如 app/Menu.php)中定义菜单时,每个条目需明确指定 'permission' 字段,值为 Spatie 权限包中已创建的权限字符串:
'Users' => ['route' => 'admin.users.index', 'permission' => 'users.index']'Create User' => ['route' => 'admin.users.create', 'permission' => 'users.create']- 子菜单、按钮、操作列里的链接也一样,只要需要控制可见性,就配一个唯一且已注册的 permission 名
确保权限与角色正确关联
用 Spatie 包管理权限时,别直接操作数据库中间表。统一使用它的方法分配:
- 创建权限:
Permission::create(['name' => 'users.index']) - 创建角色:
Role::create(['name' => 'editor']) - 给角色赋权限:
$role->givePermissionTo('users.index')或批量传数组 - 给用户绑角色:
$user->assignRole('editor')(不是attach(),否则缓存不更新)
菜单渲染时动态过滤可见项
Laravel-Admin 默认不会自动隐藏无权限菜单项。你需要在菜单注册或视图渲染阶段做权限检查:
- 在菜单模型的
getMenu()方法里,对每个菜单项调用auth()->user()->can($permission)判断 - 或者在 Blade 模板中包裹菜单生成逻辑,用
@can('users.index')控制单个菜单项输出 - 推荐预加载权限并缓存角色-权限映射,避免每次渲染都查 N+1 次数据库
后台守卫(guard)必须独立且一致
这是最容易出错的一环:Laravel-Admin 后台用户通常走 admin guard,而 Spatie 默认绑定 web guard。
- 在
config/auth.php中新增guards.admin配置,provider 指向admin_users表 - 所有 Role / Permission 模型的
$guard_name = 'admin'属性必须显式设置 - 菜单中调用
can()时,底层会按当前 guard 查权限;若没设对,永远返回 false











