目录结构
请求周期
深度挖掘 Laravel 生命周期 https://learnku.com/articles/10421/depth-mining-of-laravel-life-cycle
Laravel 请求生命周期 https://learnku.com/articles/10642/laravel-request-life-cycle
契约
接口是定义一种要实现的结构,继承类实现定义的方法。侧重于规定继承类的行为,使用者如何使用可能却有不同的地方。
而契约是一种特殊的接口,它定义了一组服务的规范,而不是具体的实现。侧重于解耦,使用者按照规范直接使用,而不用知道服务是如何实现的。说到底就是依赖倒置。
依赖倒置原则(Dependence Inversion Principle, DIP):DIP是一种软件设计的指导思想。传统软件设计中,上层代码依赖于下层代码,当下层出现变动时, 上层代码也要相应变化,维护成本较高。 而DIP的核心思想是上层定义接口,下层实现这个接口, 从而使得下层依赖于上层,降低耦合度,提高整个系统的弹性。这是一种经实践证明的有效策略。
控制反转(Inversion of Control, IoC):IoC就是DIP的一种具体思路,DIP只是一种理念、思想,而IoC是一种实现DIP的方法。 IoC的核心是将类(上层)所依赖的单元(下层)的实例化过程交由第三方来实现。控制反转 的最终目标是为了 实现项目的高内聚低耦合,而 实现这种目标 的方式则是通过 依赖注入 这种设计模式。实现控制反转时,通过将原先在模块内部完成具体实现类的实例化,移至模块的外部,然后再通过「依赖注入」的方式将具体实例「注入」到模块内即完成了对控制的反转操作。 一个简单的特征, 就是类中不对所依赖的单元有诸如 $component = new yii\component\SomeClass() 的实例化语句。
依赖注入(Dependence Injection, DI):DI是IoC的一种设计模式,是一种套路,按照DI的套路,就可以实现IoC,就能符合DIP原则。 DI的核心是把类所依赖的单元的实例化过程,放到类的外面去实现。一言以蔽之:面向接口编程。
服务定位器模式:服务定位器模式是控制反转(IoC)模式的实现,在服务定位器中注册给定接口的服务实例,然后通过接口获取服务并在应用代码中使用而不需要关心其具体实现。
控制反转容器(IoC Container):当项目比较大时,依赖关系可能会很复杂。 而IoC Container提供了动态地创建、注入依赖单元, 映射依赖关系等功能,减少了许多代码量。 Yii 设计了一个 yii\di\Container 来实现了 DI Container。
如下在Repository中使用 Cache 接口定义的 Memcached 缓存服务:
<?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)) {
//
}
}
}
上面就是高耦合的表现,必须要依赖Memcached类。
下面通过依赖一个简单的与扩展包无关的接口来改进我们的代码,来替代之前的实现方式:
<?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;
}
/**
* 根据 ID 获取订单
*
* @param int $id
* @return Order
*/
public function find($id)
{
if ($this->cache->has($id)) {
//
}
}
}
现在的代码不与任何特定的扩展包耦合了,只要 Cache 接口满足了Repository的要求,依赖注入Memcached或Redis都可以。
如何使用契约,看个事件监听器:
<?php
namespace App\Listeners;
use App\User;
use App\Events\OrderWasPlaced;
use Illuminate\Contracts\Redis\Factory;
class CacheOrderInformation
{
/**
* Redis工厂实例
*/
protected $redis;
/**
* 创建新的事件处理程序实例
*
* @param Factory $redis
* @return void
*/
public function __construct(Factory $redis)
{
$this->redis = $redis;
}
/**
* 处理事件.
*
* @param OrderWasPlaced $event
* @return void
*/
public function handle(OrderWasPlaced $event)
{
//
}
}
参考资料
Laravel 6 中文文档 https://learnku.com/docs/laravel/6.x
深度挖掘 Laravel 生命周期 https://learnku.com/articles/10421/depth-mining-of-laravel-life-cycle
深入剖析 Laravel 服务容器 https://learnku.com/articles/12575/deep-analysis-of-the-laravel-service-container
深入剖析 Laravel 服务提供者实现原理 https://learnku.com/articles/12986/in-depth-analysis-of-the-principle-of-laravel-service-provider-implementation
一文了解Laravel中的Pipeline(管道)https://www.php.cn/faq/497864.html