思维导图前阵子看了点Laravel源码,越看越乱,网上大部分中文文档都是直译,比较生涩难懂,还是决定看英文文档顺便就我的理解做下翻译整理记录下来
简介
Larvel的Contracts是一系列接口,它们定义了由框架提供的核心服务。例如,Illuminate\Contracts\Queue\Queue
定义了队列工作需要的方法,Illuminate\Contracts\Mail\Mailer
定义了发送邮件的方法。
每个contract都有框架提供的对应实现。例如,Laravel提供了不同驱动下的queue实现,还有一个SwiftMailer的mailer实现
所有的Laravel contracts都存放在他们自己的GitHub仓库中。这提供了一个快速导航,可以让你定位到可用的contracts,还有独立的,解耦的package让package开发者可以用来开发。
Contracts和门面
Laravel的门面提供了一个利用Laravel服务的简洁方法,不需要类型提示也不需要从服务容器中解析contracts。然而,用contracts可以为一个类定义明确的依赖。对于大多数应用,门面很好用。当然,如果你需要contracts提供的极度松耦合,那就读下去!
为什么要用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)) {
//
}
}
}
在这个类中,代码对指定缓存实现紧耦合。这是一个紧耦合因为我们依赖于vendor包内的固定的缓存。如果那个package内的API发生的变化,我们的代码也要变。
同样的,如果我们想要把底层缓存技术(Mecached)替换成另一个技术(Redis),我们必须修改仓库。我们的仓库无法得知谁提供了数据还有他们如何提供。
取而代之,我们可以改进我们的代码,让它们依赖于一个简单的,vendor无关的接口:
<?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;
}
}
现在代码不耦合于任何特定的vendor或者Laravel。因为contracts不包含任何实现和依赖,可以轻松为contract编写可变实现,你可以替换缓存实现而不用修改任何它服务的代码。
简洁
当所有的Laravel服务都由简单接口定义,明确给定服务提供的功能就会变得简单。contracts就像框架特征的一个简洁文档。
另外,当依赖简单的接口,你的代码理解和维护起来就更简单。不用再从庞大,复杂的类中查看哪个方法可以用,你只要参考简单干净的接口就可以了。
如何使用Contracts
你如何获得一个contract实现?这很简单。
很多类型的类都是通过服务器容器解析的,包括控制器、事件监听、中间件、队列工作甚至路由闭包。所以,你只需要在要解析的类的构造函数中类型提示接就可以获得contract的实现了。
例如,看看下面这个事件监听:
<?php
namespace App\Listeners;
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)
{
//
}
}
当你的事件监听被解析,服务容器会读取构造函数类型提示,然后注入适当的值。
网友评论