我需要編寫一個範圍來為目前登入的使用者取得項目。如果目前登入的使用者俱有查看所有項目權限,那麼我想列出系統中的所有項目,否則我想列出登入使用者建立的項目或登入的項目在使用者中透過任務分配。我嘗試在 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
中引起問題。也許另一種方法可能如下所示: