Contract

简介

Laravel 中的 Contract 是一组定义了框架核心服务的接口。例如,Illuminate\Contracts\Queue\Queue contract 定义了实现队列任务所需实现的方法,而 Illuminate\Contracts\Mail\Mailer contract 定义了发送邮件所需要实现的方法。

框架为每个 contract 都提供了一个相对应的实现。例如,Laravel 为队列提供了各种驱动的实现,以及基于 SwiftMailer 对邮件功能的实现。

Laravel 所自带的所有 contract 都有自己的 GitHub 仓库。除了方便列出所有可用的 contract 外,也可以作为独立、解耦的工具包供其他开发者使用。

Contract Vs. Facade

Laravel 中的 facades 提供了一个简单的方法来使用 Laravel 自带的服务(service),而不需要使用使用类型提示(type-hint)和在服务容器(service container)之外解析 contract。然而,使用 contract 可以明确地为类定义其依赖。对于大部分应用程序而放眼,使用 facade 就足够了。然而,如果你需要更多的低耦合,contract 就适合你了,你可以继续往下看了解更多!

为什么使用 Contract ?

你可能对于 contract 还有很多疑问。为什么要使用接口(interface)?使用接口会不会更复杂了?接下来列出的两个标题能够解释这个问题:低耦合和简单性。

低耦合

首先,我们来看一下这段和缓存功能的实现具有强耦合的代码。如下:

<?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)) {
//
}
}
}

在这个类中,代码和缓存功能的实现之间是强耦合的。因为它依赖第三方工具包中定义的缓存类。如果这个第三方工具包的 API 改变了,我们的代码也要跟着变。

同样的,如果我们希望用另一项技术(Redis)来替换掉现在所用的(Memcached),我们必须修改代码。我们所定义的类不应该依赖是谁提供了数据以及如何提供的等等细节。

比起上面代码中的做法,我们的代码应该依赖一个简单、不依赖第三方实现细节的接口:

<?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;
}
}

现在,上面的代码已经不再和具体的第三方代码甚至是 Laravel 有任何耦合了。由于 contract 工具包不包含任何实现,也不依赖其他工具包,你可以很方便地为任何 contract 创造一个实现,甚至在不需要修改任何涉及到调用缓存的代码的情况下替换为你自己的缓存实现。

简单性

当所有的 Laravel 服务(service)都通过简洁的接口进行定义,就能够很容易地确定这个服务提供的是什么功能了。可以将 contract 视为框架所提供的简洁明了的说明文档。

另外,当你依赖一个简单清晰的接口时,你的代码能够被别人轻松的理解并维护。比起在一个冗长、复杂的类中追踪哪些方法可用来说,你所面对的将是一个简洁、干净的接口。

Contract 索引

下面列出的是大部分 Laravel Contract 的索引文件,以及对应的 "facade" :

Contract 对应的Facade
Illuminate\Contracts\Auth\Guard 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\Encrption\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
Illluminate\Contracts\Logging\Log Log
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\queue\Factory Queue:: driver()
Illuminate\Contracts\Queue\Queue Queue
Illuminate\Contracts\Redis\Database Redis
Illuminate\Contracts\Routing\Registar 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()
Illuminate\Contracts\View\View  

 

 

如何使用 Contract

那么,如何实例化一个 contract 呢?其实很简单。

Laravel 中的很多类都是由 服务容器 来解析的,包括控制器、事件监听器、中间件、队列任务,甚至路由闭包(route closure)。因此,要实例化一个 contract,你可以在,类的构造函数中加入“类型提示(type-hint)”。

例如,请看下面的事件监听器:

<?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)
{
//
}
}

当事件监听器被解析的时候,服务容器将会读取构造函数的类型提示(type-hint),并注入适当的值。关于如何向服务容器注册,请参考此文档

Laravel5.1学习笔记13 系统架构5 Contract的更多相关文章

  1. Laravel5.1学习笔记i14 系统架构6 Facade

    Facades 介绍  使用 Facades Facade 类参考   #介绍 Facades provide a "static" interface to classes th ...

  2. Laravel5.1学习笔记12 系统架构4 服务容器

    Service Container 介绍 绑定的用法  绑定实例到接口 上下文绑定 标签 解析 容器事件 #介绍 The Laravel service container is a powerful ...

  3. Laravel5.1学习笔记11 系统架构3 服务提供者

    服务提供者 简介 写一个服务提供者 Register注册方法 Boot 方法 注册提供者 缓载提供者 简介 Service providers are the central place of all ...

  4. Laravel5.1学习笔记10 系统架构2 应用程序结构

    应用程序结构 简介 根目录 App 目录 为应用程序设置命名空间 简介 默认的 Laravel 应用程序结构是为了给无论构建大型还是小型应用程序都提供一个良好的开始.当然,你可以依照喜好自由地组织应用 ...

  5. Laravel5.1学习笔记9 系统架构1 请求生命周期 (待修)

    Request Lifecycle Introduction Lifecycle Overview Focus On Service Providers Introduction When using ...

  6. ODI学习笔记2--ODI产品架构

    ODI学习笔记2--ODI产品架构 ODI产品架构: ODI提供了以下几种管理工具:Designer 用于定义数据转换逻辑,这是最常用的开发工具,大部分的开发任务,包括data store的定义,in ...

  7. SQL反模式学习笔记13 使用索引

    目标:优化性能 改善性能最好的技术就是在数据库中合理地使用索引.  索引也是数据结构,它能使数据库将指定列中的某个值快速定位在相应的行. 反模式:无规划的使用索引 1.不使用索引或索引不足 2.使用了 ...

  8. springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定

    springmvc学习笔记(13)-springmvc注解开发之集合类型參数绑定 标签: springmvc springmvc学习笔记13-springmvc注解开发之集合类型參数绑定 数组绑定 需 ...

  9. Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法

    Ext.Net学习笔记13:Ext.Net GridPanel Sorter用法 这篇笔记将介绍如何使用Ext.Net GridPanel 中使用Sorter. 默认情况下,Ext.Net GridP ...

随机推荐

  1. hadoop 3.0.0新特性

    1.Minimum required Java version increased from Java 7 to Java 8 java最低支持版本变成java8 2.Support for eras ...

  2. 初次使用Let's encrypt

    wget --no-check-certificate -O shadowsocks.sh https://raw.githubusercontent.com/teddysun/shadowsocks ...

  3. noip模拟赛 都市

    分析:是一道非常有意思的题,30分的暴力的话枚举每个位置是什么数,然后排个序,用map判一下重就好了,比较麻烦. 满分做法显然不可能讨论每个位置所有的情况,肯定是有规律的,现将这n*(n-1)/2个数 ...

  4. [K/3Cloud]关于"选单"操作

    之前有些人对这块有些疑问,比如: 1.选单操作是否和下推基本一样,都是公用同一套单据转换规则,只不过下推是源单推目标单,选单是目标单去选择源单,最终操作结果一样? 2,我想实现选单的时候,选单列表先通 ...

  5. sql server internal book

    Frequently Bought Together + + Total price: $131.71 Add all three to CartAdd all three to List Buy t ...

  6. react 单元测试 (jest+enzyme)

    为什么要做单元测试 作为一个前端工程师,我是很想去谢单元测试的,因为每天的需求很多,还要去编写测试代码,感觉时间都不够用了. 不过最近开发了一个比较复杂的项目,让我感觉一旦项目大了.复杂了,而且还是多 ...

  7. TDSTCPServerTransport 的Filters

    TDSTCPServerTransport 的Filters TDSTCPServerTransport 的 Filter 属性,可以对传递的数据进行加密,压缩,再修改等,有 点注入的概念.默认情况下 ...

  8. nginx: 添加文件下载目录

    修改nginx.conf,添加如下行: location /file/ {    alias /usr/share/nginx/html/file/;    add_header Content-di ...

  9. 1.4-动态路由协议OSPF⑧

    OSPF认证(保证寻路协议级别的网络安全) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 按照参与认证的成员,进行分类: 1:链路认证(参与认证的成员 ...

  10. 1.4-动态路由协议OSPF③

    OSPF的路由汇总 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                         用默认的网络地址 因为 无论在何种路 ...