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. Android layer-list(3)

     Android layer-list(3) 在附录文章3.4的基础上,就Android layer-list再写一个较为复杂的应用. 先写布局文件,该布局涉及到LinearLayoutCompa ...

  2. 常州模拟赛d7t1 亲戚

    分析:把题目换个方式理解,就是把各个点排成一列,并且指定了若干对的先后次序,问你有多少种序列满足要求. 显然是一道dp题,直接推出方程似乎有点点困难,那么先看看数据特点. 1.有一些点满足fi=0,那 ...

  3. hdu 2844 多重背包二进制优化

    //http://www.cnblogs.com/devil-91/archive/2012/05/16/2502710.html #include<stdio.h> #define N ...

  4. vue.js编程式路由导航 --- 由浅入深

    编程式路由导航 实例中定义一个方法,这个方法绑定在标签上 然后就设置路由跳转 语法 this.$router.history.push('要跳转路由的地址') <!DOCTYPE html> ...

  5. codevs1018 单词接龙

    题目描述 Description 单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都最多在“龙”中出现两次), ...

  6. - > 动规讲解基础讲解一——01背包(模板)

    作为动态规划的基础,01背包的思想在许多动规问题中会经常出现,so,熟练的掌握01背包的思路是极其重要的: 有n件物品,第i件物品(I = 1,2,3…n)的价值是vi, 重量是wi,我们有一个能承重 ...

  7. LVS中文站点

    http://blog.csdn.net/turkeyzhou/article/details/16980161 http://zh.linuxvirtualserver.org/

  8. 《WF in 24 Hours》读书笔记 - Hour 2(1) - 第一个Workflow程序

    创建第一个Workflow项目 1. 创建Workflow项目 – 选择Workflow Console Application 2. 添加CodeActivity 3. 打开CodeActivity ...

  9. IOS开发之block应用

    非常长时间都是在学习各位大神的力作,并汲取了不少养料,在此一并谢过各位大神了. 当然了.好东西是要跟大家一起分享的,近期发现了几个很不错的个人网站,都是介绍IOS开发的.当中有唐巧.破船之长.池建强. ...

  10. LeetCode 171. Excel Sheet Column Number (Excel 表格列数字)

    Related to question Excel Sheet Column Title Given a column title as appear in an Excel sheet, retur ...