什么是 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 |
|---|---|---|
| 依赖声明 | 不需要(任何位置都可以调用) | 在构造器中显式声明 |
| 测试 | 通过 shouldReceive() mock | 通过标准的 mock 库替换实现 |
| 主要用途 | 应用内的便捷使用 | 包开发、明确的依赖管理 |
| 代码可读性 | 只需一行导入 | 构造器中的依赖一目了然 |
什么时候使用 Contract
使用 Contract 还是门面主要看个人或团队的偏好。两者都能用来构建稳固、易测的 Laravel 应用。Contract 与门面并非互斥,你完全可以在应用的一部分使用门面,另一部分使用 Contract。 Contract 在下列场景中特别有用:- 构建可与多个 PHP 框架集成的包时 — 使用
illuminate/contracts包定义与 Laravel 服务的对接,就无需在composer.json中依赖 Laravel 的具体实现。 - 希望显式表达依赖时 — 只需查看构造器就能知道类依赖了什么。
- 需要替换实现时 — 通过服务容器可以轻松替换为其他实现。
Contract 的使用方式
那么如何获取 Contract 的实现?其实非常简单。 Laravel 中许多类——控制器、事件监听器、中间件、队列任务、路由闭包等——都通过服务容器解析。因此获取 Contract 实现的方式,就是在被容器解析的类的构造器中对该接口进行「类型提示」。 例如以下事件监听器:创建自定义 Contract
通过创建自己的 Contract,可以让应用组件之间的依赖关系更加清晰。在服务提供者中绑定
在服务提供者中将 Contract 与实现绑定。
Stripe 换成其他供应商,只要修改一处绑定即可,控制器代码无需变动。
常用 Contract 一览
以下是常用 Contract 与其对应门面的对照表(部分)。| Contract | 对应门面 |
|---|---|
Illuminate\Contracts\Auth\Access\Gate | Gate |
Illuminate\Contracts\Auth\Factory | Auth |
Illuminate\Contracts\Bus\Dispatcher | Bus |
Illuminate\Contracts\Cache\Factory | Cache |
Illuminate\Contracts\Cache\Repository | Cache::driver() |
Illuminate\Contracts\Config\Repository | Config |
Illuminate\Contracts\Console\Kernel | Artisan |
Illuminate\Contracts\Container\Container | App |
Illuminate\Contracts\Encryption\Encrypter | Crypt |
Illuminate\Contracts\Events\Dispatcher | Event |
Illuminate\Contracts\Filesystem\Factory | Storage |
Illuminate\Contracts\Filesystem\Filesystem | Storage::disk() |
Illuminate\Contracts\Hashing\Hasher | Hash |
Illuminate\Contracts\Mail\Mailer | Mail |
Illuminate\Contracts\Notifications\Dispatcher | Notification |
Illuminate\Contracts\Queue\Factory | Queue |
Illuminate\Contracts\Queue\Queue | Queue::connection() |
Illuminate\Contracts\Queue\ShouldQueue | — |
Illuminate\Contracts\Redis\Factory | Redis |
Illuminate\Contracts\Routing\ResponseFactory | Response |
Illuminate\Contracts\Routing\UrlGenerator | URL |
Illuminate\Contracts\Session\Session | Session::driver() |
Illuminate\Contracts\Translation\Translator | Lang |
Illuminate\Contracts\Validation\Factory | Validator |
Illuminate\Contracts\View\Factory | View |
下一步
门面
了解门面的机制以及测试方式。