Lumen框架—升級改造之路-倉儲層
倉儲層與邏輯層搭建
Lumen官方文件: https://lumen.laravel.com/docs/5.5
我的專案地址: https://github.com/BusinessL/big-lumen
1.Lumen基礎框架中,並不包含倉儲層,與業務邏輯層,所以我們在app資料夾下,新建兩個資料夾(Repositories、Services)。另外新建Models資料夾,用來存放資料來源檔案。
別害怕在Lumen預設目錄以外建立 其他目錄 ,根據 SOLID 的 單一職責 原則,class功能越多,責任也越多,因此違法 單一職責 原則,所以你應該將你的程式分割成更小的部分,每個部分都有它專屬的功能,而不是一個class功能包山包海,所以整個架構體系不應該只有MVC三個部分,放手根據你的需求建立適當的目錄,並將適當的class放到該目錄,只要我們的class有namespace幫我們分類即可。
如何使用倉儲層?
使用理由:在 CRUD 中,CUD 比較穩定,但 R 的部分則千變萬化,大部分的業務邏輯都在描述 R 的部分,若將業務邏輯寫在 controller 或 model 都不適當,會造成 controller 與 model 肥大,造成日後難以維護。
注意:使用 repository 之後, model 僅當成Eloquent class 即可, 不要 包含業務邏輯,僅保留以下部分 :
①基礎屬性:例如 $fillable、$hidden 等。
②Method: relation類的 method,例如 hasMany() 與 belongsTo() 等。
倉儲層建立:
在 倉儲層與邏輯層搭建 一節中,我已經建立了Repositories資料夾,這個資料夾用來存放倉儲檔案。再重申一下,倉儲的定義,它是資料訪問層,與底層MySQL、Oracle等進行資料互動。
底層的資料層是多變的,我們這裡根據 依賴倒置原則 (Dependence Inversion Principle),是程式要依賴於抽象介面(interface),不要依賴於具體實現。簡單的說就是要求對抽象進行程式設計,不要對實現進行程式設計,這樣就降低了客戶與實現模組間的耦合。
下面我們在倉儲Repositories資料夾中,再新建兩個資料夾用來存放介面及其實現,取名為 Contracts 與 Eloquents 。Contracts存放介面,Eloquents用來存放介面的實現。
首先,我們在倉儲層中,新建一個BASE介面檔案(BaseInterface)與它的抽象類實現(BaseEloquent),可以在其中定義通用方法,具體參見我的程式碼庫 https://github.com/BusinessL/big-lumen 。
BaseInterface檔案內容如下所示:
<?php namespace App\Repositories\Contracts; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; interface BaseInterface { /** *更新 */ public function update(array $where, array $attributes); }
BaseEloquent內容如下所示
<?php namespace App\Repositories\Eloquents; use App\Repositories\Contracts\BaseInterface; abstract class BaseEloquent implements BaseInterface { /** * Instance that extends Illuminate\Database\Eloquent\Model * * @var Model */ protected $model; /** * Constructor */ public function __construct() { $this->makeModel(); } /** * Specify Model class name. * * @return mixed */ abstract public function model(); /** * 注入 * @return Model|mixed * @throws GeneralException */ public function makeModel() { $model = app()->make($this->model()); return $this->model = $model; } /** *更新 */ public function update(array $where, array $attributes) { return $this->model->where($where)->update($attributes); } }
注意:一個類需要繫結、註冊至容器中,才能被“製造”。對,一個類要被容器所能夠提取,必須要先註冊至這個容器。既然 Laravel 稱這個容器叫做服務容器,那麼我們需要某個服務,就得先註冊、繫結這個服務到容器,那麼提供服務並繫結服務至容器的東西,就是服務提供者(Service Provider)。如下程式碼使用bind繫結方法。
示例程式碼如下:
<?php namespace App\Providers; use Illuminate\Support\ServiceProvider; class RepositoriesServiceProvider extends ServiceProvider { /** * Indicates if loading of the provider is deferred. * * @var bool */ protected $defer = true; /** * Register any application services. * * @return void */ public function register() { $this->app->bind( \App\Repositories\Contracts\UserInterface::class, \App\Repositories\Eloquents\UserEloquent::class ); } }
好了,現在我們就可以定義每個model的資料訪問檔案,繼承BaseEloquent並實現相應的介面了。
下一節,來講解下Model層,欄位轉換功能以及Transformer工具的使用。