前陣子看了點(diǎn)Laravel源碼篓像,越看越亂动遭,網(wǎng)上大部分中文文檔都是直譯善茎,比較生澀難懂明垢,還是決定看英文文檔順便就我的理解做下翻譯整理記錄下來
簡介
Larvel的Contracts是一系列接口蚣常,它們定義了由框架提供的核心服務(wù)。例如痊银,Illuminate\Contracts\Queue\Queue
定義了隊列工作需要的方法抵蚊,Illuminate\Contracts\Mail\Mailer
定義了發(fā)送郵件的方法。
每個contract都有框架提供的對應(yīng)實(shí)現(xiàn)溯革。例如贞绳,Laravel提供了不同驅(qū)動下的queue實(shí)現(xiàn),還有一個SwiftMailer的mailer實(shí)現(xiàn)
所有的Laravel contracts都存放在他們自己的GitHub倉庫中鬓照。這提供了一個快速導(dǎo)航熔酷,可以讓你定位到可用的contracts,還有獨(dú)立的,解耦的package讓package開發(fā)者可以用來開發(fā)豺裆。
Contracts和門面
Laravel的門面提供了一個利用Laravel服務(wù)的簡潔方法拒秘,不需要類型提示也不需要從服務(wù)容器中解析contracts。然而臭猜,用contracts可以為一個類定義明確的依賴躺酒。對于大多數(shù)應(yīng)用,門面很好用蔑歌。當(dāng)然羹应,如果你需要contracts提供的極度松耦合降宅,那就讀下去绊寻!
為什么要用Contracts
你可能有很多關(guān)于contracts的問題。為什么要用接口戚丸?用接口會不會更復(fù)雜劫灶?讓我們從下面幾點(diǎn)來挖掘用接口的理由:松耦合和簡潔裸违。
松耦合
首先,讓我們回顧一段緩存首先緊耦合的代碼:
<?php
namespace App\Orders;
class Repository
{
/**
* The cache instance.
*/
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)緊耦合供汛。這是一個緊耦合因?yàn)槲覀円蕾囉趘endor包內(nèi)的固定的緩存。如果那個package內(nèi)的API發(fā)生的變化涌穆,我們的代碼也要變怔昨。
同樣的,如果我們想要把底層緩存技術(shù)(Mecached)替換成另一個技術(shù)(Redis)宿稀,我們必須修改倉庫趁舀。我們的倉庫無法得知誰提供了數(shù)據(jù)還有他們?nèi)绾翁峁?/p>
取而代之,我們可以改進(jìn)我們的代碼祝沸,讓它們依賴于一個簡單的矮烹,vendor無關(guān)的接口:
<?php
namespace App\Orders;
use Illuminate\Contracts\Cache\Repository as Cache;
class Repository
{
/**
* The cache instance.
*/
protected $cache;
/**
* Create a new repository instance.
*
* @param Cache $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
}
現(xiàn)在代碼不耦合于任何特定的vendor或者Laravel巡蘸。因?yàn)閏ontracts不包含任何實(shí)現(xiàn)和依賴,可以輕松為contract編寫可變實(shí)現(xiàn)擂送,你可以替換緩存實(shí)現(xiàn)而不用修改任何它服務(wù)的代碼悦荒。
簡潔
當(dāng)所有的Laravel服務(wù)都由簡單接口定義,明確給定服務(wù)提供的功能就會變得簡單嘹吨。contracts就像框架特征的一個簡潔文檔搬味。
另外,當(dāng)依賴簡單的接口蟀拷,你的代碼理解和維護(hù)起來就更簡單碰纬。不用再從龐大,復(fù)雜的類中查看哪個方法可以用问芬,你只要參考簡單干凈的接口就可以了悦析。
如何使用Contracts
你如何獲得一個contract實(shí)現(xiàn)?這很簡單此衅。
很多類型的類都是通過服務(wù)器容器解析的强戴,包括控制器、事件監(jiān)聽挡鞍、中間件骑歹、隊列工作甚至路由閉包。所以墨微,你只需要在要解析的類的構(gòu)造函數(shù)中類型提示接就可以獲得contract的實(shí)現(xiàn)了道媚。
例如,看看下面這個事件監(jiān)聽:
<?php
namespace App\Listeners;
use App\User;
use App\Events\NewUserRegistered;
use Illuminate\Contracts\Redis\Database;
class CacheUserInformation
{
/**
* The Redis database implementation.
*/
protected $redis;
/**
* Create a new event handler instance.
*
* @param Database $redis
* @return void
*/
public function __construct(Database $redis)
{
$this->redis = $redis;
}
/**
* Handle the event.
*
* @param NewUserRegistered $event
* @return void
*/
public function handle(NewUserRegistered $event)
{
//
}
}
當(dāng)你的事件監(jiān)聽被解析翘县,服務(wù)容器會讀取構(gòu)造函數(shù)類型提示最域,然后注入適當(dāng)?shù)闹怠?/p>