Laravel项目查询Scope问题:权限控制与截止日期排序优化
解决Laravel Project模型Scope的权限与排序问题
需求回顾
- 拥有
view-all-projects权限的管理员:返回系统所有项目 - 普通用户:仅返回自己创建的项目,或自己被分配了任务的项目
- 排序规则:项目按「即将到期→还有充足时间→已过期」的顺序排列
原代码问题分析
- 排序失效:原代码中
latest()默认按created_at降序,后续的orderBy('end_date', 'desc')被覆盖,导致排序不符合预期 - 管理员数据异常:最初的嵌套关联查询可能引发数据过滤错误,修改后的简化查询解决了数据获取问题,但缺失了关联预加载和自定义排序逻辑
完整解决方案
1. 完善scopeForUser方法
整合权限判断、关联预加载、预算计算和自定义排序逻辑:
public function scopeForUser($query, User $user) { // 统一处理关联预加载和预算统计 $query->withBudget() ->with(['customer:id,company_id' => ['company:id,name']]); // 管理员权限判断 if ($user->hasPermissionTo('view-all-projects')) { return $this->applyDueDateSort($query); } // 普通用户的项目过滤规则 return $query->where(function ($query) use ($user) { $query->where('user_id', $user->id) ->orWhereIn('id', function ($subQuery) use ($user) { $subQuery->select('project_id') ->from('tasks') ->where('user_id', $user->id); }); })->tap(function ($query) { $this->applyDueDateSort($query); }); } // 抽离排序逻辑,复用性更强 private function applyDueDateSort($query) { return $query->orderByRaw(" CASE -- 即将到期:未来7天内的项目,优先级最高 WHEN end_date >= NOW() AND end_date <= DATE_ADD(NOW(), INTERVAL 7 DAY) THEN 1 -- 充足时间:超过7天的项目,优先级次之 WHEN end_date > DATE_ADD(NOW(), INTERVAL 7 DAY) THEN 2 -- 已过期:截止日期已过的项目,优先级最低 WHEN end_date < NOW() THEN 3 -- 无截止日期的项目,放在最后 ELSE 4 END ASC, -- 同优先级内按截止日期升序,最早到期的排最前 end_date ASC "); }
2. 保留scopeWithBudget方法不变
public function scopeWithBudget($query) { return $query->addSelect(['budget' => function ($subQuery) { $subQuery->selectRaw('sum(cost)') ->from('tasks') ->whereColumn('project_id', 'projects.id'); }]); }
3. Action调用逻辑保持原样
<?php namespace App\Actions; use App\Models\Project; use Illuminate\View\View; class ListProjects { public function __invoke(): View { $projects = Project::forUser(auth()->user())->get(); return view('projects.index', ['projects' => $projects, 'projectsCount' => $projects->count()]); } }
核心优化说明
- 把排序逻辑抽成独立方法,避免重复代码,后续调整规则更方便
- 统一处理关联预加载和预算计算,减少重复的查询构建代码
- 用
orderByRaw实现自定义优先级排序,精准匹配业务需求 - 修复了原代码中排序被覆盖的问题,同时保留了管理员和普通用户的正确数据过滤逻辑
内容的提问来源于stack exchange,提问作者Kingsley
相关产品推荐
相关产品推荐

