Laravel 8 通过引入 Laravel Jetstream,模型工厂类,迁移压缩,队列批处理,改善速率限制,队列改进,动态 Blade 组件,Tailwind 分页视图, 时间测试助手,artisan serve 的改进,事件监听器的改进,以及各种其他错误修复和可用性改进,对 Laravel 7.x 继续进行了改善。
简介
Laravel 的契约是一组接口,它们由框架提供并定义了核心服务。
例如,illuste\Contracts\Queue\Queue
契约定义了排队作业所需的方法,而 illuste\Contracts\Mail\Mailer
契约定义了发送邮件所需的方法。
每个契约都有由框架提供的相应实现。
例如,Laravel 提供了一个包含各种驱动程序的队列实现,还有一个由 SwiftMailer 提供支持的邮件程序实现等等。
所有的 Laravel 契约都存在于 它们各自的 GitHub 仓库。
这为所有可用的契约提供了一个快速的参考点,以及一个可以被开发人员使用的独立的包。
契约(Contracts) Vs. 外观(Facades)
Laravel 的 Facades 和辅助函数提供了一种利用 Laravel 服务的简单方法,无需类型提示就可以从服务容器中解析契约。
在大多数情况下,每个 Facade 都有一个等效的契约。
和 Facades(它不要求我们在类的构造函数中引入它们)不同,契约允许我们为类定义显式依赖关系。 一些开发人员更喜欢以这种方式显式定义其依赖项,所以更喜欢使用契约;而另外的开发人员则享受 Facade 带来的便利。
两者各有优劣之处,具体看大家的需求和应用场景。
何时使用契约
正如在其他地方所讨论的,使用契约或 Facades 的许多决定将取决于个人喜好和开发团队的喜好。
契约和 Facades 均可用于创建功能强大且经过良好测试的 Laravel 应用程序。 只要聚焦在类的职责是单一的,我们会发现使用契约还是 Facades 之间的实际差异其实很小。
但是,我们可能仍然对契约有几个疑问。 例如,为什么要使用接口? 使用接口不是更复杂吗?
让我们将使用接口的原因归纳为以下两个原因:松耦合和简单性。
松耦合
首先,让我们回顾一些与缓存实现紧密耦合的代码。考虑以下:
<?php namespace App\Orders; class Repository { /** * 缓存实例 */ protected $cache; /** * 创建一个新的仓库实例 * * @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 { /** * 缓存实例 */ protected $cache; /** * 创建一个新的仓库实例 * * @param Cache $cache * @return void */ public function __construct(Cache $cache) { $this->cache = $cache; } }
现在,该代码尚未耦合到任何特定的供应商。
由于契约包不包含任何实现且没有依赖关系,因此我们可以轻松地编写任何给定契约的替代实现,从而使我们可以替换缓存实现,而无需修改任何消费缓存的代码。
简单性
当 Laravel 的所有服务都被整齐地定义在简单的接口中时,很容易确定给定服务提供的功能。契约是框架功能的简明文档。
此外,当我们依赖简单的接口时,我们的代码更容易理解和维护。我们可以引用一个简单、干净的接口,而不是跟踪大型、复杂的类中有哪些方法可用。
如何使用契约
那么,如何实现契约呢?它其实很简单。
Laravel 中的许多类都是通过 服务容器 解析的,包括控制器、事件侦听器、中间件、队列任务,甚至路由闭包。因此,要实现契约,我们只需在被解析的类的构造函数中「类型提示」接口。
例如,查看此事件侦听器:
<?php namespace App\Listeners; use App\Events\OrderWasPlaced; use App\Models\User; use Illuminate\Contracts\Redis\Factory; class CacheOrderInformation { /** * Redis 工厂实现 */ protected $redis; /** * 创建一个事件处理实例 * * @param Factory $redis * @return void */ public function __construct(Factory $redis) { $this->redis = $redis; } /** * 处理事件 * * @param OrderWasPlaced $event * @return void */ public function handle(OrderWasPlaced $event) { // } }