# 架构 —— 契约(Contracts)
## 1、简介
Laravel的契约是指框架提供的一系列定义核心服务的接口。比如,`Illuminate\Contracts\Queue\Queue`契约定义了队列任务需要的方法,`Illuminate\Contracts\Mail\Mailer`契约定义了发送邮件所需要的方法。
每一个契约都有框架提供的相应实现。比如,Laravel提供了多个驱动的队列实现,邮件实现则由 [SwiftMailer](http://swiftmailer.org/)驱动。
所有的Laravel契约都有其[GitHub库](https://github.com/illuminate/contracts),这为所有有效的契约提供了快速入门指南,同时也可以作为独立、解耦的包被包开发者使用。
### 1.1 契约(Contracts) VS 门面(Facades)
Laravel的门面为Laravel服务的使用提供了一个简便的方式——不再需要从服务容器中类型提示和解析契约。然而,使用契约允许你为类定义明确的依赖,在大多数应用中,使用门面刚刚好,但是,如果你需要更多更多松耦合,那么契约无疑是合适的,继续看下去!
## 2、为什么使用契约?
关于契约你可能存有疑问。为什么要全部使用这些契约接口?难道使用契约接口不是更复杂?下面让我们从这两个方面来说明使用契约接口的原因:松耦合和简单。
### 2.1 松耦合
首先,让我们看看一些缓存实现的紧密耦合代码:
~~~
<?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都是无关的。由于契约包不包含任何实现和依赖,你可以轻松的为给定契约编写可选实现代码,你可以随意替换缓存实现而不用去修改任何缓存消费代码。
### 2.2 简单
当所有Laravel服务都统一在简单接口中定义,很容易判断给定服务提供的功能。契约可以充当框架特性的简明[文档](http://laravelacademy.org/tags/%e6%96%87%e6%a1%a3 "View all posts in 文档")。
此外,基于简单接口,代码也更容易理解和维护。在一个庞大而复杂的类中,与其追踪哪些方法时有效的,不如转向简单、干净的接口。
## 3、契约列表
下面是Laravel契约列表,以及其对应的“门面”
| 契约 | 引用门面 |
| --- | --- |
| [Illuminate\Contracts\Auth\Guard](https://github.com/illuminate/contracts/blob/master/Auth/Guard.php) | Auth |
| [Illuminate\Contracts\Auth\PasswordBroker](https://github.com/illuminate/contracts/blob/master/Auth/PasswordBroker.php) | Password |
| [Illuminate\Contracts\Bus\Dispatcher](https://github.com/illuminate/contracts/blob/master/Bus/Dispatcher.php) | Bus |
| [Illuminate\Contracts\Broadcasting\Broadcaster](https://github.com/illuminate/contracts/blob/master/Broadcasting/Broadcaster.php) | |
| [Illuminate\Contracts\Cache\Repository](https://github.com/illuminate/contracts/blob/master/Cache/Repository.php) | Cache |
| [Illuminate\Contracts\Cache\Factory](https://github.com/illuminate/contracts/blob/master/Cache/Factory.php) | Cache::driver() |
| [Illuminate\Contracts\Config\Repository](https://github.com/illuminate/contracts/blob/master/Config/Repository.php) | Config |
| [Illuminate\Contracts\Container\Container](https://github.com/illuminate/contracts/blob/master/Container/Container.php) | App |
| [Illuminate\Contracts\Cookie\Factory](https://github.com/illuminate/contracts/blob/master/Cookie/Factory.php) | Cookie |
| [Illuminate\Contracts\Cookie\QueueingFactory](https://github.com/illuminate/contracts/blob/master/Cookie/QueueingFactory.php) | Cookie::queue() |
| [Illuminate\Contracts\Encryption\Encrypter](https://github.com/illuminate/contracts/blob/master/Encryption/Encrypter.php) | Crypt |
| [Illuminate\Contracts\Events\Dispatcher](https://github.com/illuminate/contracts/blob/master/Events/Dispatcher.php) | Event |
| [Illuminate\Contracts\Filesystem\Cloud](https://github.com/illuminate/contracts/blob/master/Filesystem/Cloud.php) | |
| [Illuminate\Contracts\Filesystem\Factory](https://github.com/illuminate/contracts/blob/master/Filesystem/Factory.php) | File |
| [Illuminate\Contracts\Filesystem\Filesystem](https://github.com/illuminate/contracts/blob/master/Filesystem/Filesystem.php) | File |
| [Illuminate\Contracts\Foundation\Application](https://github.com/illuminate/contracts/blob/master/Foundation/Application.php) | App |
| [Illuminate\Contracts\Hashing\Hasher](https://github.com/illuminate/contracts/blob/master/Hashing/Hasher.php) | Hash |
| [Illuminate\Contracts\Logging\Log](https://github.com/illuminate/contracts/blob/master/Logging/Log.php) | Log |
| [Illuminate\Contracts\Mail\MailQueue](https://github.com/illuminate/contracts/blob/master/Mail/MailQueue.php) | Mail::queue() |
| [Illuminate\Contracts\Mail\Mailer](https://github.com/illuminate/contracts/blob/master/Mail/Mailer.php) | Mail |
| [Illuminate\Contracts\Queue\Factory](https://github.com/illuminate/contracts/blob/master/Queue/Factory.php) | Queue::driver() |
| [Illuminate\Contracts\Queue\Queue](https://github.com/illuminate/contracts/blob/master/Queue/Queue.php) | Queue |
| [Illuminate\Contracts\Redis\Database](https://github.com/illuminate/contracts/blob/master/Redis/Database.php) | Redis |
| [Illuminate\Contracts\Routing\Registrar](https://github.com/illuminate/contracts/blob/master/Routing/Registrar.php) | Route |
| [Illuminate\Contracts\Routing\ResponseFactory](https://github.com/illuminate/contracts/blob/master/Routing/ResponseFactory.php) | Response |
| [Illuminate\Contracts\Routing\UrlGenerator](https://github.com/illuminate/contracts/blob/master/Routing/UrlGenerator.php) | URL |
| [Illuminate\Contracts\Support\Arrayable](https://github.com/illuminate/contracts/blob/master/Support/Arrayable.php) | |
| [Illuminate\Contracts\Support\Jsonable](https://github.com/illuminate/contracts/blob/master/Support/Jsonable.php) | |
| [Illuminate\Contracts\Support\Renderable](https://github.com/illuminate/contracts/blob/master/Support/Renderable.php) | |
| [Illuminate\Contracts\Validation\Factory](https://github.com/illuminate/contracts/blob/master/Validation/Factory.php) | Validator::make() |
| [Illuminate\Contracts\Validation\Validator](https://github.com/illuminate/contracts/blob/master/Validation/Validator.php) | |
| [Illuminate\Contracts\View\Factory](https://github.com/illuminate/contracts/blob/master/View/Factory.php) | View::make() |
| [Illuminate\Contracts\View\View](https://github.com/illuminate/contracts/blob/master/View/View.php) | |
## 4、如何使用契约
那么,如果获取一个契约的实现呢?相当简单。
Laravel中大部分类是通过[服务容器](http://laravelacademy.org/post/93.html)进行解析的,包括控制器、事件监听器、中间件、队列任务,甚至路由闭包等。因此,想要获取一个契约的实现,可以在被解析的类的构造函数中类型提示该契约接口。
例如,看看事件监听器的代码:
~~~
<?php
namespace App\Listeners;
use App\User;
use App\Events\NewUserRegistered;
use Illuminate\Contracts\Redis\Database;
class CacheUserInformation{
/**
* Redis数据库实现
*/
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)
{
//
}
}
~~~
当事件监听器被解析时,服务容器会读取类的构造函数上的类型提示,然后注入适当的值。想要了解更多关于服务容器的相关内容,可以查看其[文档](http://laravelacademy.org/post/93.html)。
- 前言
- 序言
- 序言 ―― 发行版本说明
- 序言 ―― 升级指南
- 序言 ―― 贡献代码
- 开始
- 开始 ―― 安装及配置
- 开始 ―― Laravel Homestead
- 基础
- 基础 ―― HTTP路由
- 基础 ―― HTTP 中间件
- 基础 ―― HTTP 控制器
- 基础 ―― HTTP 请求
- 基础 ―― HTTP 响应
- 基础 ―― 视图
- 基础 ―― Blade模板
- 架构
- 架构 ―― 一次请求的生命周期
- 架构 ―― 应用目录结构
- 架构 ―― 服务提供者
- 架构 ―― 服务容器
- 架构 ―― 契约
- 架构 ―― 门面
- 数据库
- 数据库 ―― 起步
- 数据库 ―― 查询构建器
- 数据库 ―― 迁移
- 数据库 ―― 填充数据
- Eloquent ORM
- Eloquent ORM ―― 起步
- Eloquent ORM ―― 关联关系
- Eloquent ORM ―― 集合
- Eloquent ORM ―― 调整器
- Eloquent ORM ―― 序列化
- 服务
- 服务 ―― 用户认证
- 服务 ―― Artisan 控制台
- 服务 ―― Laravel Cashier(交易)
- 服务 ―― 缓存
- 服务 ―― 集合
- 服务 ―― Laravel Elixir
- 服务 ―― 加密
- 服务 ―― 错误&日志
- 服务 ―― 事件
- 服务 ―― 文件系统/云存储
- 服务 ―― 哈希
- 服务 ―― 帮助函数
- 服务 ―― 本地化
- 服务 ―― 邮件
- 服务 ―― 包开发
- 服务 ―― 分页
- 服务 ―― 队列
- 服务 ―― Redis
- 服务 ―― Session
- 服务 ―― Envoy 任务运行器(SSH任务)
- 服务 ―― 任务调度
- 服务 ―― 测试
- 服务 ―― 验证