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. 威纶通 与 信捷XC\XD系列PLC 通讯

    第一次使用信捷XD系列PLC正式做个项目,用的触摸屏为威纶通的 MT6071iP (注意:下面内容同样适用于 信捷XC系列PLC ,除信捷XC与XD系列编程软件不一样,其余接线设置实测均一样 ) 目前 ...

  2. noip模拟赛 第K小数

    [问题描述]有两个正整数数列,元素个数分别为N和M.从两个数列中分别任取一个数相乘,这样一共可以得到N*M个数,询问这N*M个数中第K小数是多少.[输入格式]输入文件名为number.in.输入文件包 ...

  3. noip模拟赛 小Y的问题

    [问题描述]有个孩子叫小 Y,一天,小 Y 拿到了一个包含 n 个点和 n-1 条边的无向连通图, 图中的点用 1~n 的整数编号.小 Y 突发奇想,想要数出图中有多少个“Y 字形”.一个“Y 字形” ...

  4. 转载 - Struts2基于XML配置方式实现对action的所有方法进行输入校验

    出处:http://www.cnblogs.com/Laupaul/archive/2012/03/15/2398360.html http://www.blogjava.net/focusJ/arc ...

  5. jQuery动态添加表格1

    用jquery的append方法在指定行的后面新增一行tr,会把新增的行的html追加到指定行的html里面 content +="<tr><td>123</t ...

  6. JAVA学习课本内容总结

    二.基本类型 数组 枚举 1.基本类型 逻辑类型 boolean (true/false) 整数类型 byte(8位)  short(16)  int(32)  long(64) 浮点类型 float ...

  7. 基础算法(java版本)

    Practice Author: Dorae Date: 2018年10月11日13:57:44 转载请注明出处 具体代码请移步git 基础算法 图 Prim Kruskal Dijkstra Flo ...

  8. JAVA虚拟机运行时内存划分--运行时数据区域

    Java虚拟机在执行java程序时会把内存划分为以下几个不同的数据区域: java虚拟机内存划分(运行时)1.线程私有的: 程序计数器(Program Counter Register):可以看作当前 ...

  9. keil编译后生成的M51文件解析

    通过*.m51文件我们能够清楚的看到单片机存储器的使用情况,以及能够看到每一个变量包含局部变量的位置. 之前碰到一个问题,相同的程序,在small模式下编译后执行没问题,但在large模式下能够编译. ...

  10. Cannot update identity column &#39;XXX&#39;

    Sqlserver -- 怎样改动设置主键的id能够手动更新? #1 打开表的设计界面 #2 将主键id的is Identity的属性改成No 这样就能够通过Update语句来更新表的主键id了. 怎 ...