🦄 2024 独立开发者训练营,一起创业!(早鸟优惠在1天后结束)查看介绍 / 立即报名 →

Laravel 5 中文手册(十一):合同 Contracts

Laravel 的合同(Contracts)就是在框架里定义核心服务的一些接口。比如,一个 Queue 合同定义了队列工作需要用到的一些方法,Mailer 合同里边定义了发送邮件要用的一些方法。

框架为每个合同都提供了一个对应的实施。比如,Laravel 提供了一个 Queue 实施,里面有各种驱动,Mailer 实施里面用的是 SwiftMailer 。

所有的 Laravel 合同都在各种的 Github 仓库里。这为所有可用的合同,都提供了一个可以快速查看参考的地方,这样其它的开发者可以使用这些独立的,解耦的包。

为什么要用合同

你可能会有些疑问,为什么要用合同,使用接口干啥,这不是更复杂吗?下面介绍两个主要的原因,松耦合与简洁。

松耦合

先来看点实施缓存的紧耦合的代码:

<?php namespace App\Orders;

class Repository {

    /**
     * The cache.
     */
    protected $cache;

    /**
     * Create a new repository instance.
     *
     * @param  \Package\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 {

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

}

现在,代码不再跟一个特定的 vendor 绑定到一块儿了,甚至跟 Laravel 也一样。合同包里不包含实施也没有依赖,你可以简单的为任何合同去写一个替代的实施,这样你可以在不通知任何使用缓存的代码的情况下,替换掉你的缓存实施。

简洁

所有 Laravel 的服务都是用的简单的接口定义的,这样就很容易确定哪些功能来自哪些服务。合同的作用就是为架构的功能提供一个简洁的文档。别把方法放到一个巨大又复杂的类里面,使用简单,整洁的接口。这样你的代码就会很容易明白与维护。

合同参考

下面是 Laravel 里的大部分合同,还有跟它们对应的 facade。

Contract Laravel 4.x Facade
Illuminate\Contracts\Auth\Guard Auth
Illuminate\Contracts\Auth\PasswordBroker Password
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

如何创建合同

怎么样去实施合同?在 Laravel 里面的大部分类都是通过 Service Container 去 resolved ,包括控制器,事件监听器,过滤器,队列工作,甚至 Closures 路由。要去实施一个合同,你只需要在要 resolved 类的构造函数里面去 type-hint 接口。比如,看一下,下面这个 event handler :

<?php namespace App\Handlers\Events;

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

class CacheUserInformation {

    /**
     * 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  NewUserRegistered  $event
     * @return void
     */
    public function handle(NewUserRegistered $event)
    {
        //
    }

}

当事件监听器被 resolved 以后,Service Container 会去读取在类的构造函数上的 type-hint ,然后会注入适当的值。了解怎么样在 Service Container 上注册东西,可以查看这个文档

Laravel Laravel5 中文手册
微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

14696
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点