如何扩展Laravel spatie/laravel-permission的can与givePermissionTo方法
扩展权限系统的
can与givePermissionTo方法,支持模块维度校验与授权 需求背景
已为role_has_permissions表新增模块字段,需实现:
- 权限校验时关联模块字段,支持
$user->can('权限标识', '模块ID')格式调用 - 权限授予时关联模块字段,支持
$role->givePermissionTo('权限标识', '模块ID')格式调用 - 实现相同权限名在不同模块下的区分,例如:角色拥有「汽车租赁账单管理(Manage billing)」权限,但无「巴士租赁账单管理(Manage billing)」权限
1. 扩展can方法(用户权限校验)
在App\Models\User模型中重写can方法,加入模块参数的校验逻辑:
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Auth\Access\Authorizable; class User extends Authenticatable implements AuthorizableContract { use Authorizable; /** * 重写can方法,支持模块维度权限校验 * * @param string $ability 权限标识 * @param mixed $arguments 额外参数(此处传入模块ID) * @return bool */ public function can($ability, $arguments = []) { $moduleId = is_array($arguments) ? ($arguments[0] ?? null) : $arguments; // 未传入模块ID时,执行原有逻辑 if (!$moduleId) { return parent::can($ability, $arguments); } // 校验当前用户角色是否拥有对应模块下的目标权限 return $this->roles() ->whereHas('permissions', function ($query) use ($ability, $moduleId) { $query->where('name', $ability) ->where('module_id', $moduleId); // 替换为你的模块字段名 }) ->exists(); } }
2. 扩展givePermissionTo方法(角色权限授予)
在App\Models\Role模型中扩展givePermissionTo方法,支持传入模块ID并关联存储:
use Spatie\Permission\Models\Role as SpatieRole; class Role extends SpatieRole { /** * 扩展givePermissionTo方法,支持模块维度权限授予 * * @param string|array|\Spatie\Permission\Models\Permission $permissions 权限标识/对象 * @param string|null $moduleId 模块ID * @return $this */ public function givePermissionTo($permissions, $moduleId = null) { $permissionModels = $this->getPermissionModels($permissions); // 未传入模块ID时,执行原有逻辑 if (!$moduleId) { return parent::givePermissionTo($permissions); } foreach ($permissionModels as $permission) { // 避免重复添加相同模块下的权限 if (!$this->permissions() ->where('permission_id', $permission->id) ->where('module_id', $moduleId) // 替换为你的模块字段名 ->exists()) { $this->permissions()->attach($permission, ['module_id' => $moduleId]); } } $this->load('permissions'); return $this; } }
使用示例
权限授予
// 给角色授予汽车租赁模块的"Manage billing"权限 $role->givePermissionTo('Manage billing', 'CAR_RENTAL'); // 给角色授予巴士租赁模块的"PRINT_INVOICE"权限 $role->givePermissionTo('PRINT_INVOICE', 'BUS_RENTAL');
权限校验
// 校验用户是否拥有汽车租赁模块的"Manage billing"权限 $user->can('Manage billing', 'CAR_RENTAL'); // 返回true // 校验用户是否拥有巴士租赁模块的"Manage billing"权限 $user->can('Manage billing', 'BUS_RENTAL'); // 返回false
内容的提问来源于stack exchange,提问作者rzshss
相关产品推荐
相关产品推荐

