鍍金池/ 教程/ PHP/ 契約
門面
Laravel Homestead
安裝及配置
測試
HTTP 中間件
加密
升級指南
幫助函數(shù)
應(yīng)用目錄結(jié)構(gòu)
集合
新手入門指南-簡單任務(wù)管理系統(tǒng)
任務(wù)調(diào)度
查詢構(gòu)建器
視圖
驗(yàn)證
Laravel Cashier(訂購&支付&發(fā)票)
本地化
隊列
調(diào)整器
分頁
文件系統(tǒng)/云存儲
貢獻(xiàn)代碼
哈希
HTTP 控制器
緩存
遷移
HTTP 請求
Laravel Elixir
發(fā)行版本說明
Envoy 任務(wù)運(yùn)行器(SSH任務(wù))
序列化
Session
起步
帶用戶功能的任務(wù)管理系統(tǒng)
起步
用戶授權(quán)
郵件
事件
填充數(shù)據(jù)
HTTP 路由
服務(wù)提供者
Blade 模板引擎
包開發(fā)
用戶認(rèn)證
Artisan 控制臺
HTTP 響應(yīng)
集合
服務(wù)容器
關(guān)聯(lián)關(guān)系
一次請求的生命周期
契約
Redis
錯誤&日志

契約

1、簡介

Laravel 的契約是指框架提供的一系列定義核心服務(wù)的接口。比如,Illuminate\Contracts\Queue\Queue 契約定義了隊列任務(wù)需要的方法,Illuminate\Contracts\Mail\Mailer 契約定義了發(fā)送郵件所需要的方法。

每一個契約都有框架提供的相應(yīng)實(shí)現(xiàn)。比如,Laravel 提供了多個驅(qū)動的隊列實(shí)現(xiàn),郵件實(shí)現(xiàn)則由 SwiftMailer 驅(qū)動。

所有的 Laravel 契約都有其 GitHub 庫,這為所有有效的契約提供了快速入門指南,同時也可以作為獨(dú)立、解耦的包被包開發(fā)者使用。

1.1 契約(Contracts) VS 門面(Facades)

Laravel 的門面為 Laravel 服務(wù)的使用提供了一個簡便的方式——不再需要從服務(wù)容器中類型提示和解析契約。然而,使用契約允許你為類定義明確的依賴,在大多數(shù)應(yīng)用中,使用門面剛剛好,但是,如果你需要更多更多松耦合,那么契約無疑是合適的,繼續(xù)看下去!

2、為什么使用契約?

關(guān)于契約你可能存有疑問。為什么不直接全部使用接口?難道使用接口不是更復(fù)雜?讓我們從這兩個因素來提取使用接口的原因:松耦合和簡單。

2.1 松耦合

首先,讓我們看看一些緩存實(shí)現(xiàn)的緊耦合代碼:

<?php

namespace App\Orders;

class Repository{
    /**
     * 緩存
     */
    protected $cache;

    /**
     * 創(chuàng)建一個新的 Repository 實(shí)例
     *
     * @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))    {
            //
        }
    }
}

在這個類中,代碼和給定緩存實(shí)現(xiàn)緊密耦合,因?yàn)槲覀兓谝粋€來自包的具體的緩存類,如果報的 API 變了,那么相應(yīng)的,我們的代碼必須做修改。 類似的,如果我們想要替換底層的緩存技術(shù)(Memcached)為別的技術(shù)實(shí)現(xiàn)(Redis),我們將再一次不得不修改我們的代碼庫。我們的代碼庫應(yīng)該并不知道誰提供的數(shù)據(jù)或者數(shù)據(jù)是怎么提供的。

我們可以基于一種簡單的、與提供者無關(guān)的接口來優(yōu)化我們的代碼,從而替代上述那種實(shí)現(xiàn):

<?php

namespace App\Orders;

use Illuminate\Contracts\Cache\Repository as Cache;

class Repository{
    /**
     * 創(chuàng)建一個新的 Repository 實(shí)例
     *
     * @param  Cache  $cache
     * @return void
     */
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }
}

現(xiàn)在代碼就不與任何特定提供者耦合,甚至與 Laravel 都是無關(guān)的。由于契約包不包含任何實(shí)現(xiàn)和依賴,你可以輕松的為給定契約編寫可選實(shí)現(xiàn)代碼,你可以隨意替換緩存實(shí)現(xiàn)而不用去修改任何緩存消費(fèi)代碼。

2.2 簡單

當(dāng)所有 Laravel 服務(wù)都統(tǒng)一在簡單接口中定義,很容易判斷給定服務(wù)提供的功能。契約可以充當(dāng)框架特性的簡明文檔。

此外,基于簡單接口,代碼也更容易理解和維護(hù)。在一個龐大而復(fù)雜的類中,與其追蹤哪些方法時有效的,不如轉(zhuǎn)向簡單、干凈的接口。

3、契約列表

下面是 Laravel 契約列表,以及其對應(yīng)的“門面”

http://wiki.jikexueyuan.com/project/laravel-5.1/images/2.png" alt="" />

4、如何使用契約

那么,如果獲取一個契約的實(shí)現(xiàn)呢?相當(dāng)簡單。 Laravel 中大部分類是通過服務(wù)容器進(jìn)行解析的,包括控制器、事件監(jiān)聽器、中間件、隊列任務(wù),甚至路由閉包等。因此,想要獲取一個契約的實(shí)現(xiàn),可以在被解析的類的構(gòu)造函數(shù)中類型提示該契約接口。 例如,看看事件監(jiān)聽器的代碼:

<?php

namespace App\Listeners;

use App\User;
use App\Events\NewUserRegistered;
use Illuminate\Contracts\Redis\Database;

class CacheUserInformation{
    /**
     * Redis 數(shù)據(jù)庫實(shí)現(xiàn)
     */
    protected $redis;

    /**
     * 創(chuàng)建一個新的事件處理器實(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)聽器被解析時,服務(wù)容器會讀取類的構(gòu)造函數(shù)上的類型提示,然后注入適當(dāng)?shù)闹?。想要了解更多關(guān)于服務(wù)容器的相關(guān)內(nèi)容,可以查看其文檔。

上一篇:門面下一篇:貢獻(xiàn)代碼