Laravel 的 Contracts 是一組定義了框架核心服務(wù)的接口( interfaces )。例如,Queue
contract 定義了隊(duì)列任務(wù)所需要的方法,而 Mailer
contract 定義了發(fā)送 e-mail 需要的方法。
在 Laravel 框架里,每個(gè) contract 都提供了一個(gè)對(duì)應(yīng)的實(shí)現(xiàn)。例如, Laravel 提供了有多種驅(qū)動(dòng)的 Queue
的實(shí)現(xiàn),而根據(jù) SwiftMailer 實(shí)現(xiàn)了 Mailer
。
Laravel 所有的 contracts 都放在各自的 Github repository。除了提供了所有可用的 contracts 一個(gè)快速的參考,也可以單獨(dú)作為一個(gè)低耦合的擴(kuò)展包讓其他擴(kuò)展包開發(fā)者使用。
你可能有很多關(guān)于 contracts 的問(wèn)題。如為什么要使用接口?使用接口會(huì)不會(huì)變的更復(fù)雜?
讓我們用下面的標(biāo)題來(lái)解釋為什么要使用接口:低耦合和簡(jiǎn)單性。
首先,看一些強(qiáng)耦合的緩存實(shí)現(xiàn)代碼。如下:
<?php namespace App\Orders;class Repository { /** * The cache. */ protected $cache; /** * Create a new repository instance. * * @param \SomePackage\Cache\Memcached $cache * @return void */ public function __construct(\SomePackage\Cache\Memcached $cache) { $this->cache = $cache; } /** * Retrieve an Order by ID. * * @param int $id * @return Order */ public function find($id) { if ($this->cache->has($id)) { // } }}
在上面的類里,代碼跟緩存實(shí)現(xiàn)之間是強(qiáng)耦合。理由是它會(huì)依賴于擴(kuò)展包庫(kù)( package vendor )的特定緩存類。一旦這個(gè)擴(kuò)展包的 API 更改了,我們的代碼也要跟著改變。
同樣的,如果想要將底層的緩存技術(shù)(比如 Memcached )抽換成另一種(像 Redis ),又一次的我們必須修改這個(gè) repository 類。我們的 repository 不應(yīng)該知道這么多關(guān)于誰(shuí)提供了數(shù)據(jù),或是如何提供等等細(xì)節(jié)。
比起上面的做法,我們可以改用一個(gè)簡(jiǎn)單、和擴(kuò)展包無(wú)關(guān)的接口來(lái)改進(jìn)代碼:
<?php namespace App\Orders;use Illuminate\Contracts\Cache\Repository as Cache;class Repository { /** * Create a new repository instance. * * @param Cache $cache * @return void */ public function __construct(Cache $cache) { $this->cache = $cache; }}
現(xiàn)在上面的代碼沒有跟任何擴(kuò)展包耦合,甚至是 Laravel。既然 contracts 擴(kuò)展包沒有包含實(shí)現(xiàn)和任何依賴,你可以很簡(jiǎn)單的對(duì)任何 contract 進(jìn)行實(shí)現(xiàn),你可以很簡(jiǎn)單的寫一個(gè)替換的實(shí)現(xiàn),甚至是替換 contracts,讓你可以替換緩存實(shí)現(xiàn)而不用修改任何用到緩存的代碼。
當(dāng)所有的 Laravel 服務(wù)都簡(jiǎn)潔的使用簡(jiǎn)單的接口定義,就能夠很簡(jiǎn)單的決定一個(gè)服務(wù)需要提供的功能。** 可以將 contracts 視為說(shuō)明框架特色的簡(jiǎn)潔文檔。**
除此之外,當(dāng)你依賴簡(jiǎn)潔的接口,你的代碼能夠很簡(jiǎn)單的被了解和維護(hù)。比起搜索一個(gè)大型復(fù)雜的類里有哪些可用的方法,你有一個(gè)簡(jiǎn)單,干凈的接口可以參考。
以下是大部分 Laravel Contracts 的參考,以及相對(duì)應(yīng)的 "facade"
所以,要如何實(shí)現(xiàn)一個(gè) contract?實(shí)際上非常的簡(jiǎn)單。很多 Laravel 的類都是經(jīng)由 service container 解析,包含控制器,事件監(jiān)聽,過(guò)濾器,隊(duì)列任務(wù),甚至是閉包。所以,要實(shí)現(xiàn)一個(gè) contract,你可以在類的構(gòu)造器使用「類型提示」解析類。例如,看下面的事件處理程序:
<?php namespace App\Handlers\Events;use App\User;use App\Events\NewUserRegistered;use Illuminate\Contracts\Redis\Database;class CacheUserInformation { /** * Redis 數(shù)據(jù)庫(kù)實(shí)現(xiàn) */ protected $redis; /** * 建立新的事件處理實(shí)例 * * @param Database $redis * @return void */ public function __construct(Database $redis) { $this->redis = $redis; } /** * 處理事件 * * @param NewUserRegistered $event * @return void */ public function handle(NewUserRegistered $event) { // }}
當(dāng)事件監(jiān)聽被解析時(shí),服務(wù)容器會(huì)經(jīng)由類構(gòu)造器參數(shù)的類型提示,注入適當(dāng)?shù)闹怠R涝趺醋?cè)更多服務(wù)容器,參考這個(gè)文檔。
更多建議: