前言
設計一個 Controller 和 Repository 都會使用到的 Query 特徵機制。
構想
在 Repository 定義好取得資源的方法,並預先寫好 where
和 with
查詢。
1
| $user->projects()->where($this->where)->with($this->with)->findOrFail($project->id);
|
在 Controller 使用以下方式,取得特定資料。
1 2 3 4 5
| $this->setQuery([ 'where' => [ 'private' => false, ], ]);
|
在 Controller 使用以下方式,取得關聯資料。
1 2 3
| $this->setQuery([ 'with' => $request->with, ]);
|
做法
在 app/Contracts
資料夾的 ProjectInterface.php
檔,定義一個 getUserProject()
方法,第三個參數是 $query
。
1 2 3 4 5 6 7 8 9
| namespace App\Contracts;
use App\User; use App\Project;
interface ProjectInterface { public function getUserProject(User $user, Project $project, array $query = []); }
|
在 app/Http/Controllers/Api/User
資料夾的 ProjectController.php
檔,使用 Queryable
特徵機制,並使用 getUserProject()
方法,從 Repository 取得特定使用者的所有專案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| namespace App\Http\Controllers\Api\User;
use App\Project; use App\Traits\Queryable; use Illuminate\Http\Request; use App\Http\Controllers\Api\ApiController; use App\Contracts\ProjectInterface as Repository; use App\Http\Resources\ProjectResource as Resource;
class ProjectController extends ApiController { use Queryable;
protected $request;
protected $reposotory;
public function __construct(Request $request, Repository $reposotory) { parent::__construct();
$this->request = $request;
$this->reposotory = $reposotory;
$this->setQuery([ 'with' => $request->with, ]); }
public function show(Project $project) { $this->setQuery([ 'where' => [ 'private' => false, ], ]);
$project = $this->reposotory->getUserProject($this->user, $project, $this->query);
return new Resource($project); } }
|
在 app/Traits/Queryable.php
檔定義 setQuery()
以及 castQuery()
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| namespace App\Traits;
trait Queryable {
protected $query = [];
protected $with;
protected $where;
protected function setQuery(array $queries) { foreach($queries as $key => $value) { $this->query[$key] = $value; } }
protected function castQuery(array $query) { $where = $query['where'] ?? [];
$this->where = $where;
$with = explode(',', $query['with'] ?? '');
$this->with = $with[0] ? $with : []; } }
|
在 app/Repositories
資料夾的 ProjectRepository.php
檔使用 $this->castQuery()
方法,將 $query
注入,即可使用 $this->where
以及 $this->with
調用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| namespace App\Repositories;
use App\User; use App\Project; use App\Traits\Queryable; use App\Contracts\ProjectInterface;
class ProjectRepository implements ProjectInterface { use Queryable;
public function getUserProject(User $user, Project $project, array $query = []) { $this->castQuery($query);
return $user->projects()->where($this->where)->with($this->with)->findOrFail($project->id); } }
|