repository 上手 « 關於網路那些事...
安裝
composer require prettus/l5-repository
設定 ServiceProvider
如果是 >= laravel5.5 ,ServiceProvider 會自動設定好
其他版本要在 config/app.php 增加
'providers' => [ ... Prettus\Repository\Providers\RepositoryServiceProvider::class, ],
發布設定 設定完成多出一個設定檔: /config/repository.php
php artisan vendor:publish --provider "Prettus\Repository\Providers\RepositoryServiceProvider"
手動註冊 RepositoryServiceProvider
在一開始,要先手動在 app/Providers/[email protected] 新增 RepositoryServiceProvider
$this->app->register(RepositoryServiceProvider::class);
檢查
可以透過查詢 artisan 瞭解目前已經新增了哪些功能,用法會陸續說明
php artisan
簡介
- entity
即 Model, 為了避免與原有Laravel架構混淆,特別用 Entitys 來做區隔,在 Entity 只負責接資料表
- repository
只針對單一 Entity,處理一個資料表的行為
Model ---> Repository --...-> Controller
- Criteria
如果有些 Repository 查詢條件經常使用到,可以將查詢的方法放在 Criteria,重複使用
他使用的邏輯,偏向於,在原有Repository 再疊加 Criteria 規則
在 l5-repository 架構並沒有分出 Service 這層來處理商業邏輯,
因此,關於多個 Repository 組成的商業邏輯,也可放在 Criteria 裡面處理即可
MOdel ---> Repository | MOdel ---> Repository | ---> Criteria --..-> Controller MOdel ---> Repository |
- Presenter 我們常常需要將資料庫紀錄的內容進行轉換,例如,性別會用 1, 0 的方式紀錄,在輸出給使用者之前,會轉換成 男, 女 針對 Controller 從 Repository或 Service 取得結果,返回給 View 之前,有些資料需要經過格式轉換,就會在 Presenter 處理
Model ---> Repository --...-> Controller -> (Presenter) -> View MOdel ---> Repository | MOdel ---> Repository | ---> Service --..-> Controller -> (Presenter) -> View MOdel ---> Repository |
- transform
有時,在同一個 Repository or Service ,我們只希望丟出少數的資料 例如,使用者只需要返回name 與 email ,這時就能透過 transform 處理
Model ---> Repository --...-> Controller -> (transform) -> Response MOdel ---> Repository | MOdel ---> Repository | ---> Service --..-> Controller -> (transform) -> Response MOdel ---> Repository |
- Validator 驗證皆放置在這裡面處理,預設會自動生成新增及更新的驗證
建立好基本 migration
接下來會以 members 來進行範例說明, 這裡,我們建立一個 members migration 並且包含 name 及 email 欄位
artisan make:migration create_members_table
<?php ... Schema::create('members', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->string('email')->unique(); $table->softDeletes(); $table->timestamps(); });
執行 migrate
php artisan migrate
建立 Model
在 l5-repository 為了避免混淆,會將 Model 以 Entitys 方式管理
php artisan make:entity 名稱 //例如 php artisan make:entity members
在建立過程中,會自動詢問是否要同步建立 Presenter, Transformer, Validator, Controller
php artisan make:entity Members Would you like to create a Presenter? [y|N] (yes/no) [no]: > yes App\Transformers\MembersTransformerPresenter created successfully. Would you like to create a Transformer? [y|N] (yes/no) [no]: > yes Transformer created successfully. Would you like to create a Validator? [y|N] (yes/no) [no]: > yes Validator created successfully. Would you like to create a Controller? [y|N] (yes/no) [no]: > yes
透過自動新增的好處是,會自動在 app/Providers/[email protected] 新增 binding
這裡 binging 的用意是,在某些地方會引用 repository,出問題時會容易混淆,因此這裡會透過一個 Interface 隔開
$this->app->bind(\App\Repositories\MembersRepository::class, \App\Repositories\MembersRepositoryEloquent::class);
Controller
透過 make:entity 可以自行決定要產生哪些功能,其中包括了 Controller
在預設生成的 Controller 裡麵包含了 index, store, show, edit , update, destroy
- index 返回所有資料
- store 儲存一筆資料
- show 顯示指定id資料
- update 更新資料
- destroy 刪除指定id資料
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Http\Requests; use Prettus\Validator\Contracts\ValidatorInterface; use Prettus\Validator\Exceptions\ValidatorException; use App\Http\Requests\MembersCreateRequest; use App\Http\Requests\MembersUpdateRequest; use App\Repositories\MembersRepository; use App\Validators\MembersValidator; /** * Class MembersController. * * @package namespace App\Http\Controllers; */ class MembersController extends Controller { /** * @var MembersRepository */ protected $repository; /** * @var MembersValidator */ protected $validator; /** * MembersController constructor. * * @param MembersRepository $repository * @param MembersValidator $validator */ public function __construct(MembersRepository $repository, MembersValidator $validator) { $this->repository = $repository; $this->validator = $validator; } /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria')); $members = $this->repository->all(); $myTest = $this->repository->myCustomRepo(); if (request()->wantsJson()) { return response()->json([ 'data' => $members, 'test' => $myTest ]); } return view('members.index', compact('members')); } /** * Store a newly created resource in storage. * * @param MembersCreateRequest $request * * @return \Illuminate\Http\Response * * @throws \Prettus\Validator\Exceptions\ValidatorException */ public function store(MembersCreateRequest $request) { try { $this->validator->with($request->all())->passesOrFail(ValidatorInterface::RULE_CREATE); $member = $this->repository->create($request->all()); $response = [ 'message' => 'Members created.', 'data' => $member->toArray(), ]; return response()->json($response); } catch (ValidatorException $e) { return response()->json([ 'error' => true, 'message' => $e->getMessageBag() ]); } } /** * Display the specified resource. * * @param int $id * * @return \Illuminate\Http\Response */ public function show($id) { $member = $this->repository->find($id); if (request()->wantsJson()) { return response()->json([ 'data' => $member, ]); } return view('members.show', compact('member')); } /** * Show the form for editing the specified resource. * * @param int $id * * @return \Illuminate\Http\Response */ public function edit($id) { $member = $this->repository->find($id); return view('members.edit', compact('member')); } /** * Update the specified resource in storage. * * @param MembersUpdateRequest $request * @param string $id * * @return Response * * @throws \Prettus\Validator\Exceptions\ValidatorException */ public function update(MembersUpdateRequest $request, $id) { try { $this->validator->with($request->all())->passesOrFail(ValidatorInterface::RULE_UPDATE); $member = $this->repository->update($request->all(), $id); $response = [ 'message' => 'Members updated.', 'data' => $member->toArray(), ]; return response()->json($response); } catch (ValidatorException $e) { return response()->json([ 'error' => true, 'message' => $e->getMessageBag() ]); } } /** * Remove the specified resource from storage. * * @param int $id * * @return \Illuminate\Http\Response */ public function destroy($id) { $deleted = $this->repository->delete($id); return response()->json([ 'message' => 'Members deleted.', 'deleted' => $deleted, ]); } }
許可權檢查
比較特別的是,store 與 update 在使用時,預設要經過 auth() 流程 可以在 app/Requests/ 看到這兩個對應的 Request 處理,也可以寫入 Request 的檢查規則 MembersCreateRequest.php MembersUpdateeRequest.php
如果在 store, update 不想使用 auth,只需要在這兩隻檔案中 authorize() return true 即可
Route
可以在 api.php 設定對應的 route
<?php ... Route::prefix('members')->group(function () { Route::get('get', '[email protected]'); Route::get('show/{id}', '[email protected]'); Route::post('store', '[email protected]'); Route::post('update/{id}', '[email protected]'); Route::post('destroy/{id}', '[email protected]'); });
Criteria
建立 Criteria
php artisan make:criteria Mytest
會自動在 app/Criteria/ 建立 MytestCriterias.php
可以直接在 apply 裡面新增你想要的查詢規則
<?php .. public function apply($model, RepositoryInterface $repository) { return $model->where('id', 2); }
接著就能在 Controller 使用,原則上他是以累加方式來套上這些規則
$this->repository->pushCriteria(new MytestCriteria()); $members = $this->repository->all();
RequestCriteria
l5-repository 提供一個預設的 RequestCriteria
裡面提供了一整套查詢規則,相當方便
首先要先在 MembersRepositoryEloquent 新增可以被搜尋的欄位
並且可以在 boot 直接引用 RequestCriteria (這個在自動生成時,就會直接幫你加上)
<?php class MembersRepositoryEloquent extends BaseRepository implements MembersRepository { protected $fieldSearchable = [ 'name', 'email' ]; ... /** * Boot up the repository, pushing criteria */ public function boot() { $this->pushCriteria(app(RequestCriteria::class)); }
也可以在 controller 裡面手動匯入
<?php ... $this->repository->pushCriteria(app('Prettus\Repository\Criteria\RequestCriteria')); $members = $this->repository->all();
接著就可以參考下方規則,進行搜尋
http://prettus.local/users?search=John%20Doe
or
http://prettus.local/users?search=John&searchFields=name:like
or
http://prettus.local/[email protected]&searchFields=email:=
or
http://prettus.local/users?search=name:John Doe;email:[email protected]
or
http://prettus.local/users?search=name:John;email:[email protected]&searchFields=name:like;email:=
詳細內容可以參考官方檔案
如果你喜歡我們的文章內容,請在這裡按個讚 Tweet