Contracts

未匹配的标注
本文档最新版为 10.x,旧版本可能放弃维护,推荐阅读最新版!

契约

简介

Laravel 的契约是指框架提供的一系列定义核心服务的接口。例如 Illuminate\Contracts\Queue\Queue 契约定义了队列任务需要实现的方法,而 Illuminate\Contracts\Mail\Mailer 契约定义了发送邮件所需要实现的方法。

每一个契约都有框架提供相应的实现。例如 Laravel 为队列提供了多个驱动的实现,邮件则由 SwiftMailer驱动实现。

所有的契约都有其 对应的 GitHub 仓库。这为所有可用的契约提供了一个快速入门的指南,同时也可以单独作为低耦合的扩展包被开发者使用。

契约 Vs. Facades

Laravel 的 facades 和辅助函数都提供了一种使用 Laravel 服务的简单方法,既不需类型提示,也不需要从服务容器中解析契约。大多情况下,每一个 Facades 都有一个等效的契约。

在 Facades 中,你不需要在构造函数中做类型提示,但是契约需要你在类中明确的定义依赖。一些开发者倾向于使用契约这种明确定义依赖的方式,而其他开发者则更喜欢 Facades 带来的便捷。

{tip} 对于大多数的应用程序而言,不管是使用 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 服务都统一使用简单接口定义时,就会很容易判断给定服务提供的功能。可以将契约视为说明框架功能的简洁文档

除此之外,基于简单接口,代码更容易理解和维护。在一个庞大而复杂的类中,与其追踪哪些方法是有效的,倒不如直接查找一个简单、干净的接口来参考更为妥当。

如何使用契约

那么如何使用契约呢?其实很简单。

Laravel 中有很多类都是通过 服务容器,进行解析,包括控制器,以及事件监听器、中间件、队列任务,甚至路由闭包。所以,实现一个契约,你只需要在被解析的类的构造函数中添加契约接口即可。

例如,下面这个事件监听器:

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

当事件监听器被解析的时候,服务容器会读取构造函数中的类型提示,并注入相应的值。想要学习更多关于服务容器的注册细节,请参考 其文档.

契约参考

下表提供了所有 Laravel 契约以及其对应的 Facades :

契约 对应的 Facade
Illuminate\Contracts\Auth\Access\Authoriza...   
Illuminate\Contracts\Auth\Access\Gate Gate
Illuminate\Contracts\Auth\Authenticatable   
Illuminate\Contracts\Auth\CanResetPassword  
Illuminate\Contracts\Auth\Factory Auth
Illuminate\Contracts\Auth\Guard Auth::guard()
Illuminate\Contracts\Auth\PasswordBroker Password::broker()
Illuminate\Contracts\Auth\PasswordBrokerFa... Password
Illuminate\Contracts\Auth\StatefulGuard  
Illuminate\Contracts\Auth\SupportsBasicAut...  
Illuminate\Contracts\Auth\UserProvider  
Illuminate\Contracts\Bus\Dispatcher Bus
Illuminate\Contracts\Bus\QueueingDispatche... Bus::dispatchToQueue()
Illuminate\Contracts\Broadcasting\Factory Broadcast
Illuminate\Contracts\Broadcasting\Broadcas... Broadcast::connection()
Illuminate\Contracts\Broadcasting\ShouldBr...  
Illuminate\Contracts\Broadcasting\ShouldBr...  
Illuminate\Contracts\Cache\Factory Cache
Illuminate\Contracts\Cache\Lock  
Illuminate\Contracts\Cache\LockProvider  
Illuminate\Contracts\Cache\Repository Cache::driver()
Illuminate\Contracts\Cache\Store  
Illuminate\Contracts\Config\Repository Config
Illuminate\Contracts\Console\Application  
Illuminate\Contracts\Console\Kernel Artisan
Illuminate\Contracts\Container\Container App
Illuminate\Contracts\Cookie\Factory Cookie
Illuminate\Contracts\Cookie\QueueingFactor... Cookie::queue()
Illuminate\Contracts\Database\ModelIdentif...  
Illuminate\Contracts\Debug\ExceptionHandle...  
Illuminate\Contracts\Encryption\Encrypter Crypt
Illuminate\Contracts\Events\Dispatcher Event
Illuminate\Contracts\Filesystem\Cloud Storage::cloud()
Illuminate\Contracts\Filesystem\Factory Storage
Illuminate\Contracts\Filesystem\Filesystem Storage::disk()
Illuminate\Contracts\Foundation\Applicatio... App
Illuminate\Contracts\Hashing\Hasher Hash
Illuminate\Contracts\Http\Kernel  
Illuminate\Contracts\Mail\MailQueue Mail::queue()
Illuminate\Contracts\Mail\Mailable  
Illuminate\Contracts\Mail\Mailer Mail
Illuminate\Contracts\Notifications\Dispatc... Notification
Illuminate\Contracts\Notifications\Factory Notification
Illuminate\Contracts\Pagination\LengthAwar...  
Illuminate\Contracts\Pagination\Paginator  
Illuminate\Contracts\Pipeline\Hub  
Illuminate\Contracts\Pipeline\Pipeline  
Illuminate\Contracts\Queue\EntityResolver  
Illuminate\Contracts\Queue\Factory Queue
Illuminate\Contracts\Queue\Job  
Illuminate\Contracts\Queue\Monitor Queue
Illuminate\Contracts\Queue\Queue Queue::connection()
Illuminate\Contracts\Queue\QueueableCollec...  
Illuminate\Contracts\Queue\QueueableEntity  
Illuminate\Contracts\Queue\ShouldQueue  
Illuminate\Contracts\Redis\Factory Redis
Illuminate\Contracts\Routing\BindingRegist... Route
Illuminate\Contracts\Routing\Registrar Route
Illuminate\Contracts\Routing\ResponseFacto... Response
Illuminate\Contracts\Routing\UrlGenerator URL
Illuminate\Contracts\Routing\UrlRoutable  
Illuminate\Contracts\Session\Session Session::driver()
Illuminate\Contracts\Support\Arrayable  
Illuminate\Contracts\Support\Htmlable  
Illuminate\Contracts\Support\Jsonable  
Illuminate\Contracts\Support\MessageBag  
Illuminate\Contracts\Support\MessageProvid...  
Illuminate\Contracts\Support\Renderable  
Illuminate\Contracts\Support\Responsable  
Illuminate\Contracts\Translation\Loader  
Illuminate\Contracts\Translation\Translato... Lang
Illuminate\Contracts\Validation\Factory Validator
Illuminate\Contracts\Validation\ImplicitRu...  
Illuminate\Contracts\Validation\Rule  
Illuminate\Contracts\Validation\ValidatesW...  
Illuminate\Contracts\Validation\Validator Validator::make()
Illuminate\Contracts\View\Engine  
Illuminate\Contracts\View\Factory View
Illuminate\Contracts\View\View View::make()

本文章首发在 LearnKu.com 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://learnku.com/docs/laravel/5.7/con...

译文地址:https://learnku.com/docs/laravel/5.7/con...

上一篇 下一篇
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
贡献者:4
讨论数量: 0
发起讨论 只看当前版本


暂无话题~