首页 » Laravel 5.3 中文文档 » 正文

「Laravel 5.3 中文文档」核心概念 – Contracts

简介

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

框架中每个 contract 都有相应的实现。例如,Laravel 提供了多种驱动实现队列,以及 SwiftMailer 驱动的邮件服务的实现。

Laravel 所有的 contracts 都放在他们的 Github 代码仓库中。这为查看所有 contracts 提供了一个快速参考,降低耦合来让其他扩展包开发者使用。

Contracts Vs. Facades

Laravel 的 facades 及其辅助函数提供了一个简单的方法来使用 Laravel 的服务,不需要在服务容器之外使用类型提示以及获取 contracts。大多数情况下,每一个 facade 都有一个相应的 contract。

使用 facades,你不需要在类的构造函数中引入它们,而使用 contracts,则需要你在类中明确定义一个依赖。有些开发者更喜欢使用这种方式明确的在类中定义依赖,因而喜欢这种方法,而另一些则喜欢 facades 的便捷性。

大部分应用都不会在意你喜欢使用 contracts 还是 facades,然而,如果你是写一个扩展包的话,强烈建议你使用 contracts,因为它们更易于测试。

何时使用 Contracts

正如其他地方讨论的那样,使用 facades 还是 contracts 最终取决于你的个人喜好已经开发团队的需要。ContractsC 及 facades 都可以创建强大的、易于测试的应用。只要你的类责任明确,你会注意到 facades 和 contracts 中间并没有什么明显的区别。

然而,对于 contracts 你可能还有其他的一些问题。例如,为什么要使用接口?使用接口不是更复杂吗?让我们用下面的标题来解释为什么要使用接口:低耦合和简单性。

低耦合

首先,让我们来查看这一段和缓存功能有高耦合的代码,如下:

<?php

namespace App\Orders;

class Repository
{
    /**
     * The cache instance.
     */
    protected $cache;

    /**
     * Create a new repository instance.
     *
     * @param  \SomePackage\Cache\Memcached  $cache
     * @return void
     */
    public function __construct(\SomePackage\Cache\Memcached $cache)
    {
        $this->cache = $cache;
    }

    /**
     * Retrieve an Order by 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
{
    /**
     * The cache instance.
     */
    protected $cache;

    /**
     * Create a new repository instance.
     *
     * @param  Cache  $cache
     * @return void
     */
    public function __construct(Cache $cache)
    {
        $this->cache = $cache;
    }
}

现在上面的代码没有跟任何扩展包耦合,甚至是 Laravel。由于 contracts 不包含任何实现和依赖,你可以轻松为任何给定的 contract 编写替代实现,允许你不修改任何缓存使用处的代码就可以替换缓存实现。

简单

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

此外,但你依赖简单接口的时候,你的代码就更容易理解和维护。比起搜索一个大型复杂的类里有哪些可用的方法,你有一个简单,干净的接口可以参考。

如何使用 Contracts

那么,你如何获取一个 contract 的实现?这真的非常简单。

Laravel 中很多类型的类都是通过服务容器解析的,包括控制器、事件监听器、中间件、队列任务、甚至是路由。所以,要获取一个 contract 的实现,你可以在构造函数中为要获取的类的接口做类型提示。

例如,看下面的事件监听器:

<?php

namespace App\Listeners;

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

class CacheOrderInformation
{
    /**
     * The Redis database implementation.
     */
    protected $redis;

    /**
     * Create a new event handler instance.
     *
     * @param  Database  $redis
     * @return void
     */
    public function __construct(Database $redis)
    {
        $this->redis = $redis;
    }

    /**
     * Handle the event.
     *
     * @param  OrderWasPlaced  $event
     * @return void
     */
    public function handle(OrderWasPlaced $event)
    {
        //
    }
}

当获取到事件监听器后,服务容器将会在类的构造函数中读取类型提示,并注入一个合适的值。要查看关于在服务容器中注册事物的更多内容,请查看其文档

Contract 参考

下表提供了 Laravel 所有的 contracts 及其对应的 facades:

ContractReferences Facade
Illuminate\Contracts\Auth\FactoryAuth
Illuminate\Contracts\Auth\PasswordBrokerPassword
Illuminate\Contracts\Bus\DispatcherBus
Illuminate\Contracts\Broadcasting\Broadcaster
Illuminate\Contracts\Cache\RepositoryCache
Illuminate\Contracts\Cache\FactoryCache::driver()
Illuminate\Contracts\Config\RepositoryConfig
Illuminate\Contracts\Container\ContainerApp
Illuminate\Contracts\Cookie\FactoryCookie
Illuminate\Contracts\Cookie\QueueingFactoryCookie::queue()
Illuminate\Contracts\Encryption\EncrypterCrypt
Illuminate\Contracts\Events\DispatcherEvent
Illuminate\Contracts\Filesystem\Cloud
Illuminate\Contracts\Filesystem\FactoryFile
Illuminate\Contracts\Filesystem\FilesystemFile
Illuminate\Contracts\Foundation\ApplicationApp
Illuminate\Contracts\Hashing\HasherHash
Illuminate\Contracts\Logging\LogLog
Illuminate\Contracts\Mail\MailQueueMail::queue()
Illuminate\Contracts\Mail\MailerMail
Illuminate\Contracts\Queue\FactoryQueue::driver()
Illuminate\Contracts\Queue\QueueQueue
Illuminate\Contracts\Redis\DatabaseRedis
Illuminate\Contracts\Routing\RegistrarRoute
Illuminate\Contracts\Routing\ResponseFactoryResponse
Illuminate\Contracts\Routing\UrlGeneratorURL
Illuminate\Contracts\Support\Arrayable
Illuminate\Contracts\Support\Jsonable
Illuminate\Contracts\Support\Renderable
Illuminate\Contracts\Validation\FactoryValidator::make()
Illuminate\Contracts\Validation\Validator
Illuminate\Contracts\View\FactoryView::make()
Illuminate\Contracts\View\View

该篇属于专题:《Laravel 5.3 中文文档

发表评论