我需要编写一个范围来为当前登录的用户获取项目。如果当前登录的用户具有查看所有项目权限,那么我想列出系统中的所有项目,否则我想列出登录用户创建的项目或登录的项目在用户中通过任务分配。我尝试在 Project
模型中编写以下范围:
public function scopeForUser($query, User $user) { if ($user->can('view-all-projects')) { return $query->withBudget() ->with(['customer:id,company_id' => ['company:id,name']]) ->latest() ->orderBy('end_date', 'desc'); } return $query->withBudget() ->with(['customer:id,company_id' => ['company:id,name']]) ->where(function ($query) use ($user) { $query->where('user_id', $user->id) ->orWhereHas('users', function ($query) use ($user) { $query->where('users.id', $user->id); }) ->orWhereHas('tasks', function ($query) use ($user) { $query->where('user_id', $user->id); }); }) ->latest() ->orderBy('end_date', 'desc'); }
withBudget
的范围如下
public function scopeWithBudget($query) { return $query->addSelect(['budget' => function ($subQuery) { $subQuery->selectRaw('sum(cost)') ->from('tasks') ->whereColumn('project_id', 'projects.id'); }]); }
到目前为止,它确实有效,但不准确。有时,当我知道登录的用户是管理员并拥有所有权限时,它只会获取几个项目,而且项目也会按降序排列,我认为 created_at
而不是 end_date< /代码>
有什么想法可以解决这个问题吗?如果您需要更多信息,请告诉我
编辑 如果我删除一些查询,以下代码片段将起作用:
if ($user->hasPermissionTo('view-all-projects')) { return $query->latest(); } else { return $query->where(function ($query) use ($user) { $query->where('user_id', $user->id) ->orWhereIn('id', function ($query) use ($user) { $query->select('project_id') ->from('tasks') ->where('user_id', $user->id); }); }); }
然后我通过以下操作获取项目:
<?php namespace App\Actions; use App\Models\Project; // use Illuminate\Support\Collection; 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()]); } }
虽然上面的代码片段有效,但它没有做一件事(暂时忘记急切加载),但我需要根据截止日期之前的剩余时间列出项目。因此,它应该按顺序列出即将到期的项目、有更多时间的项目、已经到期的项目
我认为排序问题可能是您调用
latest()
以及orderBy('end_date', 'desc')
作为latest()
工作于created_at
。您可能根本不需要latest()
调用,因为您无论如何都要添加自己的排序。至于用户范围问题,我想知道您是否使用两个
orWhereHas
调用而不是whereHas
和orWhereHas 可能会在
scopeForUser
中引起问题。也许另一种方法可能如下所示: