Laravel 接口契约 Contracts

简介

Laravel 的 Contracts 是一组定义了框架核心服务的接口。例如,Illuminate\Contracts\Queue\Queue contract 定义了队列任务所需的方法,而 Illuminate\Contracts\Mail\Mailer contract 定义了发送电子邮件所需的方法。

框架对每个 contract 都提供了相应的实现。例如,Laravel 提供了一个对各种驱动程序的队列实现,以及一个由 SwiftMailer 驱动的邮件实现。

所有的 Laravel contracts 存放在他们 单独的GitHub库 。除了提供给所有可用的 contracts 一个快速的参考,还可以单独作为一个低耦合的扩展包来让其他扩展包开发者使用。

Contracts Vs. Facades

Laravel 的 facades 和辅助函数提供了一种使用 Laravel 的服务的简单方法,而不需要类型提示和解析服务容器之外的 contracts 。 在大多数情况下,每个 facade 都有一个等效 contract。

不像 facades 那样,contracts 需要显式定义依赖关系。 一些开发人员更喜欢以这种方式显式定义它们的依赖关系,因此更喜欢使用 contracts,而其他开发人员喜欢 facades 的方便性。

{tip} 大多数应用程序不论使用 facades 还是 contracts 都无所谓。 然而,如果你正在构建一个扩展包,强烈地建议使用 contracts,因为它们将更容易在包上下文中测试。

何时使用 contracts

正如其他地方所讨论的,使用 contracts 或 facades 很大程度上归结于个人品味和开发团队的品味。 contracts 和 facades 都可用于创建稳健、经过良好测试的 Laravel 应用程序。 只要你一直能关注类的功能点,你会发现使用 contracts 和 facades 之间很少有实际差异。

但是,您可能仍有几个关于 contracts 的问题。例如,为什么使用接口?是不是使用接口更复杂?使用接口的原因如下:低耦合和简单性。

低耦合

首先,让我们回顾一些与缓存实现紧密耦合的代码。如下:

<?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))    {
            //
        }
    }
}

在这个类中,代码跟给定的缓存实现紧密耦合。因为我们依赖于一个具体的 Cache 类从一个软件包供应商。如果该包的 API 更改,我们的代码也必须更改。

同样,如果我们要用另一种缓存技术( Redis )替换我们的底层缓存技术( Memcached ),我们再次必须修改我们的 Repository 。我们的 Repository 类不应该知道这么多关于谁提供了数据,或是如何提供等细节。

比起上面的做法,我们可以使用一个简单,和扩展包无关的接口来改进代码:

<?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 。由于 contracts 不包含实现和依赖,因此您可以轻松地编写任何 contracts 实现,从而替换缓存实现,而无需修改任何缓存代码。

简单性

当所有的 Laravel 服务都使用简洁的接口定义,就能够很容易决定一个服务需要提供的功能。 可以将 contracts 视为说明框架特色的简洁文档。

除此之外,当依赖的接口足够简洁时,代码的可读性和可维护性大大提高。比起搜索一个大型复杂的类里有哪些可用的方法,你有一个简单,干净的接口可以参考。

如何使用 Contracts

那么,如何获取一个 contract 实现呢?这其实很简单。

Laravel 中的许多类型的类都是通过 服务容器 解析,包括控制器,事件监听器,中间件,任务队列,甚至路由闭包。所以,要获得一个 contract 的实现,你只需要在正在解析的类的构造函数中的声明「类型约束」即可。

例如,看看这个事件监听器:

<?php

namespace App\Listeners;

use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Database;

class CacheOrderInformation
{
    /**
     * Redis 数据库实现。
     */
    protected $redis;

    /**
     * 创建事件处理器实例。
     *
     * @param  Database  $redis
     * @return void
     */
    public function __construct(Database $redis)
    {
        $this->redis = $redis;
    }

    /**
     * 处理事件。
     *
     * @param  OrderWasPlaced  $event
     * @return void
     */
    public function handle(OrderWasPlaced $event)
    {
        //
    }
}

当事件监听器被解析时,服务容器将读取类的构造函数上的类型提示,并注入对应的类实例。 想了解如何注册绑定到容器,请查看服务容器

Contract 参考

下面的表格提供了 Laravel contracts 及其对应的 facades 的参考:

Contract References Facade
Illuminate\Contracts\Auth\Factory Auth
Illuminate\Contracts\Auth\PasswordBroker Password
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Broadcasting\Broadcaster  
Illuminate\Contracts\Cache\Repository Cache
Illuminate\Contracts\Cache\Factory Cache::driver()
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactory Cookie::queue()
Illuminate\Contracts\Encryption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud  
Illuminate\Contracts\Filesystem\Factory File
Illuminate\Contracts\Filesystem\Filesystem File
Illuminate\Contracts\Foundation\Application App
Illuminate\Contracts\Hashing\Hasher Hash
Illuminate\Contracts\Logging\Log Log
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\Mail\Mailer Mail
Illuminate\Contracts\Queue\Factory Queue::driver()
Illuminate\Contracts\Queue\Queue Queue
Illuminate\Contracts\Redis\Database Redis
Illuminate\Contracts\Routing\Registrar Route
Illuminate\Contracts\Routing\ResponseFactory Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Support\Arrayable  
Illuminate\Contracts\Support\Jsonable  
Illuminate\Contracts\Support\Renderable  
Illuminate\Contracts\Validation\Factory Validator::make()
Illuminate\Contracts\Validation\Validator  
Illuminate\Contracts\View\Factory View::make()
Illuminate\Contracts\View\View  

译者署名

用户名 头像 职能 签名
@e421083458 翻译 Github求star,@e421083458 at Github

upport/Jsonable.php) |   [Illumi

results matching ""

    No results matching ""