鍍金池/ 教程/ PHP/ Contracts
Laravel Cashier
Eloquent ORM
HTTP 響應
發(fā)行說明
擴展包開發(fā)
HTTP 控制器
事件
擴展框架
Contracts
開發(fā)
配置
表單驗證
錯誤與日志
Hashing
貢獻指南
郵件
Session
遷移與數(shù)據(jù)填充
查詢構(gòu)造器
Redis
升級向?qū)?/span>
概覽
緩存
服務提供者
Envoy 任務執(zhí)行器
隊列
單元測試
服務容器
文件系統(tǒng) / 云存儲
認證
請求的生命周期
加密
模板
視圖 (View)
Laravel Homestead
Laravel 安裝指南
介紹
Command Bus
分頁
輔助方法
應用程序結(jié)構(gòu)
HTTP 路由
HTTP 請求
基本用法
本地化
HTTP 中間件
結(jié)構(gòu)生成器
Facades
Laravel Elixir

Contracts

簡介

Laravel 的 Contracts 是一組定義了框架核心服務的接口( interfaces )。例如,Queue contract 定義了隊列任務所需要的方法,而 Mailer contract 定義了發(fā)送 e-mail 需要的方法。

在 Laravel 框架里,每個 contract 都提供了一個對應的實現(xiàn)。例如, Laravel 提供了有多種驅(qū)動的 Queue 的實現(xiàn),而根據(jù) SwiftMailer 實現(xiàn)了 Mailer。

Laravel 所有的 contracts 都放在各自的 Github repository。除了提供了所有可用的 contracts 一個快速的參考,也可以單獨作為一個低耦合的擴展包讓其他擴展包開發(fā)者使用。

為什么用 Contracts?

你可能有很多關(guān)于 contracts 的問題。如為什么要使用接口?使用接口會不會變的更復雜?

讓我們用下面的標題來解釋為什么要使用接口:低耦合和簡單性。

低耦合

首先,看一些強耦合的緩存實現(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))
        {
            //
        }
    }

}

在上面的類里,代碼跟緩存實現(xiàn)之間是強耦合。理由是它會依賴于擴展包庫( package vendor )的特定緩存類。一旦這個擴展包的 API 更改了,我們的代碼也要跟著改變。

同樣的,如果想要將底層的緩存技術(shù)(比如 Memcached )抽換成另一種(像 Redis ),又一次的我們必須修改這個 repository 類。我們的 repository 不應該知道這么多關(guān)于誰提供了數(shù)據(jù),或是如何提供等等細節(jié)。

比起上面的做法,我們可以改用一個簡單、和擴展包無關(guā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)在上面的代碼沒有跟任何擴展包耦合,甚至是 Laravel。既然 contracts 擴展包沒有包含實現(xiàn)和任何依賴,你可以很簡單的對任何 contract 進行實現(xiàn),你可以很簡單的寫一個替換的實現(xiàn),甚至是替換 contracts,讓你可以替換緩存實現(xiàn)而不用修改任何用到緩存的代碼。

簡單性

當所有的 Laravel 服務都簡潔的使用簡單的接口定義,就能夠很簡單的決定一個服務需要提供的功能。可以將 contracts 視為說明框架特色的簡潔文檔.

除此之外,當你依賴簡潔的接口,你的代碼能夠很簡單的被了解和維護。比起搜索一個大型復雜的類里有哪些可用的方法,你有一個簡單,干凈的接口可以參考。

Contract 參考

以下是大部分 Laravel Contracts 的參考,以及相對應的 "facade"

Contract Laravel 4.x Facade
IlluminateContractsAuthGuard Auth
IlluminateContractsAuthPasswordBroker Password
IlluminateContractsBusDispatcher Bus
IlluminateContractsCacheRepository Cache
IlluminateContractsCacheFactory Cache::driver()
IlluminateContractsConfigRepository Config
IlluminateContractsContainerContainer App
IlluminateContractsCookieFactory Cookie
IlluminateContractsCookieQueueingFactory Cookie::queue()
IlluminateContractsEncryptionEncrypter Crypt
IlluminateContractsEventsDispatcher Event
IlluminateContractsFilesystemCloud
IlluminateContractsFilesystemFactory File
IlluminateContractsFilesystemFilesystem File
IlluminateContractsFoundationApplication App
IlluminateContractsHashingHasher Hash
IlluminateContractsLoggingLog Log
IlluminateContractsMailMailQueue Mail::queue()
IlluminateContractsMailMailer Mail
IlluminateContractsQueueFactory Queue::driver()
IlluminateContractsQueueQueue Queue
IlluminateContractsRedisDatabase Redis
IlluminateContractsRoutingRegistrar Route
IlluminateContractsRoutingResponseFactory Response
IlluminateContractsRoutingUrlGenerator URL
IlluminateContractsSupportArrayable
IlluminateContractsSupportJsonable
IlluminateContractsSupportRenderable
IlluminateContractsValidationFactory Validator::make()
IlluminateContractsValidationValidator
IlluminateContractsViewFactory View::make()
IlluminateContractsViewView

如何使用 Contracts

所以,要如何實現(xiàn)一個 contract?實際上非常的簡單。很多 Laravel 的類都是經(jīng)由 service container 解析,包含控制器,事件監(jiān)聽,過濾器,隊列任務,甚至是閉包。所以,要實現(xiàn)一個 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ù)庫實現(xiàn)
     */
    protected $redis;

    /**
     * 建立新的事件處理實例
     *
     * @param  Database  $redis
     * @return void
     */
    public function __construct(Database $redis)
    {
        $this->redis = $redis;
    }

    /**
     * 處理事件
     *
     * @param  NewUserRegistered  $event
     * @return void
     */
    public function handle(NewUserRegistered $event)
    {
        //
    }

}

當事件監(jiān)聽被解析時,服務容器會經(jīng)由類構(gòu)造器參數(shù)的類型提示,注入適當?shù)闹怠R涝趺醋愿喾杖萜鳎瑓⒖?a href="container.html">這個文檔。