什么是 Contract
Laravel 的「Contracts」是一组定义框架核心服务的接口。例如,Illuminate\Contracts\Queue\Queue Contract 定义了队列所需的方法,Illuminate\Contracts\Mail\Mailer Contract 定义了发送邮件所需的方法。
每个 Contract 都有一个由框架提供的对应实现。例如,Laravel 提供了各种驱动的队列实现,以及基于 Symfony Mailer 的邮件实现。
所有 Laravel Contract 都存放在专门的 GitHub 仓库中。这既是所有可用 Contract 的快速参考,也是一份可以在构建与 Laravel 服务对接的包时单独使用的、隔离的包。
Contract 只是接口,其运行机制与 PHP 接口完全一致。Laravel 提供了这些接口的实现,并通过服务容器注入。
Contract 与 Facade 的区别
门面和辅助函数提供了一种使用 Laravel 服务的便捷方式,而不需要在服务容器中通过类型提示解析 Contract。多数情况下,每个门面都有对应的 Contract。 门面与 Contract 的主要区别如下:什么时候使用 Contract
使用 Contract 还是门面主要看个人或团队的偏好。两者都能用来构建稳固、易测的 Laravel 应用。Contract 与门面并非互斥,你完全可以在应用的一部分使用门面,另一部分使用 Contract。 Contract 在下列场景中特别有用:- 构建可与多个 PHP 框架集成的包时 — 使用
illuminate/contracts包定义与 Laravel 服务的对接,就无需在composer.json中依赖 Laravel 的具体实现。 - 希望显式表达依赖时 — 只需查看构造器就能知道类依赖了什么。
- 需要替换实现时 — 通过服务容器可以轻松替换为其他实现。
Contract 的使用方式
那么如何获取 Contract 的实现?其实非常简单。 Laravel 中许多类——控制器、事件监听器、中间件、队列任务、路由闭包等——都通过服务容器解析。因此获取 Contract 实现的方式,就是在被容器解析的类的构造器中对该接口进行「类型提示」。 例如以下事件监听器:创建自定义 Contract
通过创建自己的 Contract,可以让应用组件之间的依赖关系更加清晰。1
定义接口
在
app/Contracts 目录中创建接口。2
创建实现类
创建实现该 Contract 的类。
3
在服务提供者中绑定
在服务提供者中将 Contract 与实现绑定。
4
通过类型提示接收注入
在控制器或其他类的构造器中进行类型提示。
Stripe 换成其他供应商,只要修改一处绑定即可,控制器代码无需变动。
常用 Contract 一览
以下是常用 Contract 与其对应门面的对照表(部分)。
完整 Contract 列表可在 illuminate/contracts 仓库查看。
下一步
门面
了解门面的机制以及测试方式。