如何更简洁地检查当前用户是否拥有指定权限(自定义实现)
自定义用户权限检查的优化实现
我拥有四张表(users、permissions、roles、roles_permissions),表结构如下:
users _______________________ | id | name | role_id | |____|______|_________| | 1 | John | 1 | |____|______|_________| roles ______________ | id | name | |____|_______| | 1 | admin | |____|_______| permissions ____________________ | id | permission | |____|_____________| | 1 | view-posts | |____|_____________| roles_permissions ________________________________ | id | permission_id | role_id | |____|_______________|_________| | 1 | 1 | 1 | |____|_______________|_________|
我想要检查当前用户是否拥有如view-posts这类指定权限,已在Permission.php模型中实现了以下方法:
public function checkPermission($permission){ $role = Auth()->user()->role_id; $id = $this->select('permissions.id')->join('role_permissions as rp', 'rp.permission_id', 'permissions.id')->where('rp.role_id', $role)->where('permission', $permission)->get()->toArray(); return $id ? true : false; }
调用方式如下:
$permission = new permission(); $check = $permission->checkPermission('view-posts');
请问是否有更简洁/更优的实现方式?
注:请勿推荐权限包,我因特定需求需使用自定义方法
优化方案
1. 直接用exists()简化查询逻辑
原方法需要获取数据转数组后判断,不如直接让数据库返回是否存在的布尔值,性能更高,代码更简洁:
// Permission.php public function checkPermission($permission) { $roleId = Auth()->user()->role_id; return $this->join('roles_permissions as rp', 'rp.permission_id', '=', 'permissions.id') ->where('rp.role_id', $roleId) ->where('permissions.permission', $permission) ->exists(); }
2. 将方法迁移到User模型,调用更直观
权限检查是针对当前用户的,把方法放到User.php里更符合逻辑,无需实例化Permission模型:
// User.php public function hasPermission($permission) { return $this->join('roles', 'users.role_id', '=', 'roles.id') ->join('roles_permissions as rp', 'roles.id', '=', 'rp.role_id') ->join('permissions', 'permissions.id', '=', 'rp.permission_id') ->where('users.id', $this->id) ->where('permissions.permission', $permission) ->exists(); }
调用时直接用:
$check = Auth()->user()->hasPermission('view-posts');
如果已经在User模型定义了和Role的关联(public function role() { return $this->belongsTo(Role::class); }),还可以简化成:
// User.php public function hasPermission($permission) { return $this->role() ->join('roles_permissions as rp', 'roles.id', '=', 'rp.role_id') ->join('permissions', 'permissions.id', '=', 'rp.permission_id') ->where('permissions.permission', $permission) ->exists(); }
3. 利用模型关联实现内存级检查(适合频繁调用场景)
提前通过关联加载用户的权限,后续检查直接在内存中判断,避免重复查库:
// User.php public function role() { return $this->belongsTo(Role::class); } // Role.php public function permissions() { return $this->belongsToMany(Permission::class, 'roles_permissions'); } // User.php中的权限检查方法 public function hasPermission($permission) { // 首次调用会加载关联,后续直接用缓存的数据 return $this->role->permissions->pluck('permission')->contains($permission); }
调用前可以预加载关联减少查询次数:
// 比如在控制器中 $user = Auth()->user()->load('role.permissions'); $check = $user->hasPermission('view-posts');
内容的提问来源于stack exchange,提问作者mmdev
相关产品推荐
相关产品推荐

