Laravel中的契約是指框架提供的一系列定義核心服務的接口。 例如 ,Illuminate\Contracts\Queue\Queue
契約定義了隊列任務須要實現的方法,Illuminate\Contracts\Mail\Mailer
契約定義了發送郵件所須要實現的方法。 php
每個契約都有框架提供的相應實現。例如,Laravel爲隊列提供了多個驅動的實現,郵件則由 SwiftMailer驅動 實現 。 html
全部Laravel契約都有其對應的GitHub庫,這爲全部有效的契約提供了快速入門指南,同時也能夠做爲獨立、解耦的包被包開發者使用。 laravel
Laravel門面爲Laravel服務的使用提供了便捷方式——再也不須要從服務容器中類型提示和契約 解析便可直接經過靜態門面調用 。有些開發者喜歡這種便捷,不過也有開發者傾向於使用契約,他們喜歡定義明確的依賴。 git
注:大多數應用中,無論你使用門面仍是契約,合適就好。不過,若是你是在構建一個擴展包,那麼就應該使用契約,由於這在擴展包中更容易測試。github
正如上面所討論的,大多數狀況下使用契約仍是門面取決於我的或團隊的喜愛,契約和門面均可以用於建立強大的、測試友好的Laravel應用。只要你保持類的職責單一,你會發現使用契約和門面並無什麼實質性的差異。 redis
可是,對契約你可能仍是有些疑問。例如,爲何要所有使用接口?使用接口是否是更復雜?下面讓咱們從兩個方面來扒一扒爲何使用接口:鬆耦合和簡單。 swift
首先,讓咱們看看一些緩存實現的緊耦合代碼:緩存
<?php namespace App\Orders; class Repository{ /** * 緩存 */ protected $cache; /** * 建立一個新的Repository實例 * * @param \SomePackage\Cache\Memcached $cache * @return void */ public function __construct(\SomePackage\Cache\Memcached $cache) { $this->cache = $cache; } /** * 經過ID獲取訂單 * * @param int $id * @return Order */ public function find($id) { if ($this->cache->has($id)) { // } } }
在這個類中,代碼和給定緩存實現緊密耦合,因爲咱們基於一個來自包的具體的緩存類,若是包的API變了,那麼相應的,咱們的代碼必須作修改。 閉包
相似的,若是咱們想要替換底層的緩存技術(Memcached)爲別的技術實現(Redis),咱們將再一次不得不修改咱們的代碼庫。咱們的代碼庫應該並不知道誰提供的數據或者數據是怎麼提供的。 框架
咱們能夠基於一種簡單的、與提供者無關的接口來優化咱們的代碼,從而替代上述那種實現:
<?php namespace App\Orders; use Illuminate\Contracts\Cache\Repository as Cache; class Repository{ /** * 建立一個新的Repository實例 * * @param Cache $cache * @return void */ public function __construct(Cache $cache) { $this->cache = $cache; } }
如今代碼就不與任何特定提供者耦合,甚至與Laravel都是無關的。因爲契約包不包含任何實現和依賴,你能夠輕鬆的爲給定契約編寫可選實現代碼,你能夠隨意替換緩存實現而不用去修改任何緩存消費代碼。
當全部Laravel服務都統一在簡單接口中定義,很容易判斷給定服務提供的功能。契約能夠充當框架特性的簡明文檔。
此外,基於簡單接口,代碼也更容易理解和維護。在一個龐大而複雜的類中,與其追蹤哪些方法是有效的,不如轉向簡單、乾淨的接口。
那麼,如何實現契約呢?這很簡單。
Laravel中不少類都是經過服務容器進行解析,包括控制器,以及監聽器、中間件、隊列任務,甚至路由閉包。因此,要實現一個契約,須要在解析類的構造函數中類型提示這個契約接口。
例如,看看下面這個事件監聽器:
<?php namespace App\Listeners; use App\User; use App\Events\OrderWasPlaced; use Illuminate\Contracts\Redis\Database; class CacheOrderInformation { /** * 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 OrderWasPlaced $event * @return void */ public function handle(OrderWasPlaced $event) { // } }
事件監聽器被解析的時候,服務容器會讀取構造函數中的類型提示,並注入適當的值。要學習更多關於服務容器的註冊細節,參考其文檔。
下面是Laravel契約列表,以及其對應的「門面」:
Contract
References Facade
Illuminate\Contracts\Auth\Factory
Auth
Illuminate\Contracts\Auth\PasswordBroker
Password
Illuminate\Contracts\Bus\Dispatcher
Bus
Illuminate\Contracts\Broadcasting\Broadcaster
Illuminate\Contracts\Cache\Repository
Cache
Illuminate\Contracts\Cache\Factory
Cache::driver()
Illuminate\Contracts\Config\Repository
Config
Illuminate\Contracts\Container\Container
App
Illuminate\Contracts\Cookie\Factory
Cookie
Illuminate\Contracts\Cookie\QueueingFactory
Cookie::queue()
Illuminate\Contracts\Encryption\Encrypter
Crypt
Illuminate\Contracts\Events\Dispatcher
Event
Illuminate\Contracts\Filesystem\Cloud
Illuminate\Contracts\Filesystem\Factory
File
Illuminate\Contracts\Filesystem\Filesystem
File
Illuminate\Contracts\Foundation\Application
App
Illuminate\Contracts\Hashing\Hasher
Hash
Illuminate\Contracts\Logging\Log
Log
Illuminate\Contracts\Mail\MailQueue
Mail::queue()
Illuminate\Contracts\Mail\Mailer
Mail
Illuminate\Contracts\Queue\Factory
Queue::driver()
Illuminate\Contracts\Queue\Queue
Queue
Illuminate\Contracts\Redis\Database
Redis
Illuminate\Contracts\Routing\Registrar
Route
Illuminate\Contracts\Routing\ResponseFactory
Response
Illuminate\Contracts\Routing\UrlGenerator
URL
Illuminate\Contracts\Support\Arrayable
Illuminate\Contracts\Support\Jsonable
Illuminate\Contracts\Support\Renderable
Illuminate\Contracts\Validation\Factory
Validator::make()
Illuminate\Contracts\Validation\Validator
Illuminate\Contracts\View\Factory
View::make()