倉儲層與邏輯層搭建
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並實現相應的接口了。
下一節,來講解下邏輯層,控制器如何使用邏輯,邏輯如何使用倉儲。
