在Laravel中如何基于用户角色实现Deal模型的访问权限控制
实现方案
推荐用Laravel内置的**策略(Policy)**实现,完全满足你逻辑解耦的需求,后续维护扩展也更方便,也可以选择直接把逻辑封装到User模型里,两种方案如下:
方案1:基于Policy实现(更符合Laravel权限设计规范)
1. 生成Deal对应的策略文件
执行Artisan命令:php artisan make:policy DealPolicy --model=Deal
生成的文件默认保存在app/Policies/DealPolicy.php。
2. 编写权限判断逻辑
在DealPolicy中定义列表查询的权限方法:
public function viewAny(User $user) { $allowedFields = []; if ($user->is_admin) $allowedFields[] = 'for_admin'; if ($user->is_management) $allowedFields[] = 'for_management'; return Deal::query() ->when(!empty($allowedFields), function ($q) use ($allowedFields) { $q->where(function ($subQ) use ($allowedFields) { foreach ($allowedFields as $field) { $subQ->orWhere($field, 1); } }); }) ->when(empty($allowedFields), fn($q) => $q->whereRaw('1=0')); } // 可选:补充单个商机的查看权限 public function view(User $user, Deal $deal) { return ($user->is_admin && $deal->for_admin) || ($user->is_management && $deal->for_management); }
3. 注册策略
在app/Providers/AuthServiceProvider.php的$policies属性中添加关联:
protected $policies = [ Deal::class => DealPolicy::class, ];
4. 控制器调用
无需在控制器写任何权限判断逻辑,直接调用即可:
public function index() { $deals = auth()->user()->can('viewAny', Deal::class)->get(); return view('deals.index', compact('deals')); }
方案2:直接封装到User模型(符合你偏好的实现方式)
直接在User模型中新增权限查询方法:
public function getAccessibleDealsQuery() { $conditions = []; if ($this->is_admin) $conditions[] = ['for_admin', 1]; if ($this->is_management) $conditions[] = ['for_management', 1]; return empty($conditions) ? Deal::whereRaw('1=0') // 无权限返回空结果 : Deal::whereOr($conditions); }
控制器中直接调用:
public function index() { $deals = auth()->user()->getAccessibleDealsQuery()->get(); return view('deals.index', compact('deals')); }
两种方案都完全和控制器解耦,后续如果要新增权限规则(比如普通员工的可见范围),只需要修改对应方法即可,不需要改动业务层代码。
内容的提问来源于stack exchange,提问作者Seven
相关产品推荐
相关产品推荐

