• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Laravel 契约Contracts 详解

武飞扬头像
juejin
帮助56

简介

Laravel 的契约是一组接口,它们由框架提供并定义了核心服务。

例如,illuste\Contracts\Queue\Queue 契约定义了排队作业所需的方法,而 illuste\Contracts\Mail\Mailer 契约定义了发送邮件所需的方法。

每个契约都有由框架提供的相应实现。

例如,Laravel 提供了一个包含各种驱动程序的队列实现,还有一个由 SwiftMailer 提供支持的邮件程序实现等等。

所有的 Laravel 契约都存在于 它们各自的 GitHub 仓库

这为所有可用的契约提供了一个快速的参考点,以及一个可以被开发人员使用的独立的包。

契约(Contracts) Vs. 外观(Facades)

Laravel 的 Facades 和辅助函数提供了一种利用 Laravel 服务的简单方法,无需类型提示就可以从服务容器中解析契约。

在大多数情况下,每个 Facade 都有一个等效的契约。

和 Facades(它不要求我们在类的构造函数中引入它们)不同,契约允许我们为类定义显式依赖关系。 一些开发人员更喜欢以这种方式显式定义其依赖项,所以更喜欢使用契约;而另外的开发人员则享受 Facade 带来的便利。

两者各有优劣之处,具体看大家的需求和应用场景。

技巧:无论我们更喜欢 Facads 还是契约,大多数应用都运行得不错。但是,如果要构建程序包,则应强烈考虑使用契约,因为它们在程序包上下文中更容易测试。

何时使用契约

正如在其他地方所讨论的,使用契约或 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)
    {
        //
    }
}

当解析事件侦听器时,服务容器将读取类的构造函数上的类型提示,并注入适当的值。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanfbbbe
系列文章
更多 icon
同类精品
更多 icon
继续加载