Laravel 的“契约”是一组接口,它们定义了框架提供的核心服务。例如,一个 Illuminate\Contracts\Queue\Queue 契约定义了队列任务所需的方法,而 Illuminate\Contracts\Mail\Mailer 契约定义了发送电子邮件所需的方法。
每个契约都有一个由框架提供的对应实现。例如,Laravel 提供了一个支持多种驱动的队列实现,以及一个由 Symfony Mailer 提供支持的邮件发送器实现。
所有 Laravel 契约都位于它们自己的 GitHub 仓库。这提供了所有可用契约的快速参考点,以及一个单一的、解耦的包,该包可在构建与 Laravel 服务交互的包时利用。
Laravel 的外观和辅助函数提供了一种简单的方式来利用 Laravel 的服务,而无需类型提示并从服务容器中解析契约。在大多数情况下,每个外观都拥有一个等效的契约。
与门面不同,它们不需要你在类的构造函数中引入,契约允许你为类定义明确的依赖。一些开发者喜欢以这种方式明确定义他们的依赖,因此更喜欢使用契约,而另一些开发者则喜欢门面带来的便利。通常情况下,大多数应用程序在开发过程中使用门面都不会有问题。
使用契约或门面的决定将取决于个人品味以及您的开发团队的品味。契约和门面都可用于创建健壮、经过充分测试的 Laravel 应用程序。契约和门面并非相互排斥。您的应用程序的某些部分可能使用门面,而其他部分则依赖契约。只要您保持类的职责集中,您就会发现使用契约和门面之间几乎没有实际差异。
一般而言,大多数应用在开发过程中可以无障碍地使用门面。如果你正在构建一个与多个 PHP 框架集成的包你可能希望使用 illuminate/contracts 包来定义你的包与 Laravel 服务的集成而无需引入 Laravel 的具体实现 在你的包的 composer.json 文件中。
那么,如何获取合约的实现呢?这实际上相当简单。
Laravel 中的许多类型的类都是通过 服务容器 解析的,包括控制器、事件监听器、中间件、队列任务,甚至路由闭包。因此,为了获取某个契约的实现,你只需在被解析的类的构造函数中“类型提示”该接口即可。
例如,看看这个事件监听器:
<?php
namespace App\Listeners;
use App\Events\OrderWasPlaced;
use App\Models\User;
use Illuminate\Contracts\Redis\Factory;
class CacheOrderInformation
{
/**
* Create the event listener.
*/
public function __construct(
protected Factory $redis,
) {}
/**
* Handle the event.
*/
public function handle(OrderWasPlaced $event): void
{
// ...
}
}当事件监听器被解析时,服务容器将读取类的构造函数上的类型提示,并注入相应的值。要了解更多关于在服务容器中注册事物的信息,请查看其文档。
此表提供了所有 Laravel 契约及其等效门面的快速参考: