laravel管道模式理解

简化版Pipeline

代码摘自 https://blog.csdn.net/qq_24095941/article/details/84970774

<?php
class Pipeline
{

    /**
     * The method to call on each pipe
     * @var string
     */
    protected $method = 'handle';

    /**
     * The object being passed throw the pipeline
     * @var mixed
     */
    protected $passable;

    /**
     * The array of class pipes
     * @var array
     */
    protected $pipes = [];

    /**
     * Set the object being sent through the pipeline
     *
     * @param $passable
     * @return $this
     */
    public function send($passable)
    {
        $this->passable = $passable;
        return $this;
    }

    /**
     * Set the method to call on the pipes
     * @param array $pipes
     * @return $this
     */
    public function through($pipes)
    {
        $this->pipes = $pipes;
        return $this;
    }

    /**
     * @param \Closure $destination
     * @return mixed
     */
    public function then(\Closure $destination)
    {
        $pipeline = array_reduce(array_reverse($this->pipes), $this->getSlice(), $destination);
        return $pipeline($this->passable);
    }


    /**
     * Get a Closure that represents a slice of the application onion
     * @return \Closure
     */
    protected function getSlice()
    {
        return function($stack, $pipe){
            return function ($request) use ($stack, $pipe) {
                return $pipe::{$this->method}($request, $stack);
            };
        };
    }

}

解读

表面看起来有点绕,其实简单理解起来就是我们现实中常说的套娃。

等闭包函数执行起来,所send的数据就会被套在闭包中间。这样就实现了所谓的中间件。

简单实例

代码摘自 https://blog.csdn.net/qq_24095941/article/details/84970774

<?php
class ALogic
{
    public static function handle($data,  $next)
    {
        print "开始 A 逻辑";
        $ret = $next($data);
        print "结束 A 逻辑";
        return $ret;
    }
}

class BLogic
{
    public static function handle($data, $next)
    {
        print "开始 B 逻辑";
        $ret = $next($data);
        print "结束 B 逻辑";
        return $ret;
    }
}

class CLogic
{
    public static function handle($data, $next)
    {
        print "开始 C 逻辑";
        $ret = $next($data);
        print "结束 C 逻辑";
        return $ret;
    }
}

$pipes = [
    ALogic::class,
    BLogic::class,
    CLogic::class
];

$data = "any things";
(new Pipeline())->send($data)->through($pipes)->then(function($data){ print $data;});

输出结果,换行是人为加上去的。

开始 A 逻辑
开始 B 逻辑
开始 C 逻辑
any things
结束 C 逻辑
结束 B 逻辑
结束 A 逻辑

等价

// 最终会返回一个闭包
return function ($request) use ($stack, $pipe) {
	return $pipe::{$this->method}($request, $stack);
};
// 闭包架构会随着array_reduce被整理成以下逻辑(伪代码):
clourse() {
    return ALogic->handle({
        BLogic->handle({
            CLogic->handle({
                // 所以可以简单理解为套娃模式
                $destination($data);
            })
        })
    });
};
// 反转管道队列是因为要后进先出,这样才能满足预期的结果。

所以管道模式最终的目的是要将过滤器分解成一个个子任务,在子任务中将数据一层层过滤。这也是laravel中间件的实现原理。


laravel管道模式理解
http://blog.icy8.cn/posts/38672/
作者
icy8
发布于
2021年2月24日
许可协议