1、简介

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

每一个契约都有框架提供的相应实现。例如,Laravel为队列提供了多个驱动的实现,邮件则由 SwiftMailer驱动 实现 。

所有Laravel契约都有其对应的GitHub库,这为所有有效的契约提供了快速入门指南,同时也可以作为独立、解耦的包被包开发者使用。

契约(Contracts) VS 门面(Facades)

Laravel门面为Laravel服务的使用提供了便捷方式——不再需要从服务容器中类型提示和契约 解析即可直接通过静态门面调用 。有些开发者喜欢这种便捷,不过也有开发者倾向于使用契约,他们喜欢定义明确的依赖。

注:大多数应用中,不管你使用门面还是契约,合适就好。不过,如果你是在构建一个扩展包,那么就应该使用契约,因为这在扩展包中更容易测试。

2、何时使用契约

正如上面所讨论的,大多数情况下使用契约还是门面取决于个人或团队的喜好,契约和门面都可以用于创建强大的、测试友好的Laravel应用。只要你保持类的职责单一,你会发现使用契约和门面并没有什么实质性的差别。

但是,对契约你可能还是有些疑问。例如,为什么要全部使用接口?使用接口是不是更复杂?下面让我们从两个方面来扒一扒为什么使用接口:松耦合和简单。

松耦合

首先,让我们看看一些缓存实现的紧耦合代码:

<?php

namespace App\Orders;

class Repository{
/**
* 缓存
*/
protected $cache; /**
* 创建一个新的Repository实例
*
* @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)) {
//
}
}
}

在这个类中,代码和给定缓存实现紧密耦合,由于我们基于一个来自包的具体的缓存类,如果包的API变了,那么相应的,我们的代码必须做修改。

类似的,如果我们想要替换底层的缓存技术(Memcached)为别的技术实现(Redis),我们将再一次不得不修改我们的代码库。我们的代码库应该并不知道谁提供的数据或者数据是怎么提供的。

我们可以基于一种简单的、与提供者无关的接口来优化我们的代码,从而替代上述那种实现:

<?php

namespace App\Orders;

use Illuminate\Contracts\Cache\Repository as Cache;

class Repository{
/**
* 创建一个新的Repository实例
*
* @param Cache $cache
* @return void
*/
public function __construct(Cache $cache)
{
$this->cache = $cache;
}
}

现在代码就不与任何特定提供者耦合,甚至与Laravel都是无关的。由于契约包不包含任何实现和依赖,你可以轻松的为给定契约编写可选实现代码,你可以随意替换缓存实现而不用去修改任何缓存消费代码。

简单

当所有Laravel服务都统一在简单接口中定义,很容易判断给定服务提供的功能。契约可以充当框架特性的简明文档

此外,基于简单接口,代码也更容易理解和维护。在一个庞大而复杂的类中,与其追踪哪些方法是有效的,不如转向简单、干净的接口。

3、如何使用契约

那么,如何实现契约呢?这很简单。

Laravel中很多类都是通过服务容器进行解析,包括控制器,以及监听器、中间件、队列任务,甚至路由闭包。所以,要实现一个契约,需要在解析类的构造函数中类型提示这个契约接口。

例如,看看下面这个事件监听器:

<?php

namespace App\Listeners;

use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Database; class CacheOrderInformation
{
/**
* 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 OrderWasPlaced $event
* @return void
*/
public function handle(OrderWasPlaced $event)
{
//
}
}

事件监听器被解析的时候,服务容器会读取构造函数中的类型提示,并注入适当的值。要学习更多关于服务容器的注册细节,参考其文档。

4、契约列表

下面是Laravel契约列表,以及其对应的“门面”:

Contract
References Facade

Illuminate\Contracts\Auth\Factory
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\Encryption\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

Illuminate\Contracts\Logging\Log
Log

Illuminate\Contracts\Mail\MailQueue
Mail::queue()

Illuminate\Contracts\Mail\Mailer
Mail

Illuminate\Contracts\Queue\Factory
Queue::driver()

Illuminate\Contracts\Queue\Queue
Queue

Illuminate\Contracts\Redis\Database
Redis

Illuminate\Contracts\Routing\Registrar
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

核心概念 —— 契约(Contracts)的更多相关文章

  1. Laravel 的核心概念

    工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...

  2. Laravel 核心概念

    工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...

  3. 领域驱动设计(DDD)部分核心概念的个人理解

    领域驱动设计(DDD)是一种基于模型驱动的软件设计方式.它以领域为核心,分析领域中的问题,通过建立一个领域模型来有效的解决领域中的核心的复杂问题.Eric Ivans为领域驱动设计提出了大量的最佳实践 ...

  4. Javascript本质第一篇:核心概念

    很多人在使用Javascript之前都至少使用过C++.C#或Java,面向对象的编程思想已经根深蒂固,恰好Javascript在语法上借鉴了Java,虽然方便了Javascript的入门,但要深入理 ...

  5. [程序设计语言]-[核心概念]-02:名字、作用域和约束(Bindings)

    本系列导航 本系列其他文章目录请戳这里. 1.名字.约束时间(Binding Time) 在本篇博文开始前先介绍两个约定:第一个是“对象”,除非在介绍面向对象语言时,本系列中出现的对象均是指任何可以有 ...

  6. spring技术核心概念纪要

    一.背景 springframework 从最初的2.5版本发展至今,期间已经发生了非常多的修正及优化.许多新特性及模块的出现,使得整个框架体系显得越趋庞大,同时也带来了学习及理解上的困难. 本文阐述 ...

  7. ElasticSearch学习笔记-01 简介、安装、配置与核心概念

    一.简介 ElasticSearch是一个基于Lucene构建的开源,分布式,RESTful搜索引擎.设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便.支持通过HTTP使用JSON进 ...

  8. Playmaker Input篇教程之引入的核心概念

    Playmaker Input篇教程之引入的核心概念 Playmaker Input引入的核心概念 Playmaker引入了4个核心概念:状态机.动作.变量和事件.了解它们是学习操作Playmaker ...

  9. Maven的几个核心概念

    POM (Project Object Model) 一个项目所有的配置都放置在 POM 文件中:定义项目的类型.名字,管理依赖关系,定制插件的行为等等.比如说,你可以配置 compiler 插件让它 ...

随机推荐

  1. Java学习笔记(二):String

    String 在Java中String是作为引用对象存在的一种数据类型,用来保存字符串. 实例化和赋值 //直接声明 String s1 = "Hello world!"; //通 ...

  2. 让sublime text 3默认新建GBK文件

    想让sublime text支持显示或者保存中文,需要安装插件convertToUTF8,具体安装可以问度娘. 安装插件以后,想让保存的html文件支持中文,可以通过ctrl+shift+C来完成.但 ...

  3. 在Linux下怎么确定哪个网卡对应哪个接口?

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  4. javax.naming.NameNotFoundException

    2015-08-27 09:53:16,463 [localhost-startStop-1] DEBUG [org.springframework.jndi.JndiTemplate] - Look ...

  5. The Trip PC/UVa IDs: 110103/10137, Popularity: B, Success rate: average Level: 1

    #include<cstdio> #include<iostream> #include<string> #include<algorithm> #in ...

  6. C# 创建移动应用

    打开VS2013 选择ASP.NET MVC4Web应用程序,点击[确定] 选择[移动应用程序]点击[确定],运行之后显示的效果如图

  7. 怎样在osg中动态的设置drawable的最近最远裁剪面

    // draw callback that will tweak the far clipping plane just    // before rendering a drawable.    s ...

  8. Cocos2d-x多语言支持解决方式

    很多其它相关内容请查看本人博客:http://www.bokeyi.com/ll/category/cocos2d-x/ 利用.plist文件让Cocos2d-x轻松支持多语言. .plist文件类似 ...

  9. delphi 去掉TreeView水平滚动条

        使用API函数:声明 FUNCTION ulong ShowScrollBar(ulong hwnd,ulong wBar,ulong bShow) LIBRARY "user32. ...

  10. myeclipse-10.7-offline-installer-windows安装图解及注意事项

    MyEclipse企业级工作平台(MyEclipseEnterprise Workbench ,简称MyEclipse)是对EclipseIDE的扩展,利用它我们能够在数据库和JavaEE的开发.公布 ...