Laravel之Pipeline1. 背景2. 基本操作3. 动手实现4. Laravel中Pipeline实现5. 总结

1. 背景

在Laravel中经常需要对一个对象,经过多个中间层处理后,才到真正处理的函数,Laravel将这种常用操作抽象出来,叫做Pipeline

2. 基本操作

interface Pipeline
{
    /**
     * Set the traveler object being sent on the pipeline.
     *
     * @param  mixed  $traveler
     * @return $this
     */
    public function send($traveler);

    /**
     * Set the stops of the pipeline.
     *
     * @param  dynamic|array  $stops
     * @return $this
     */
    public function through($stops);

    /**
     * Set the method to call on the stops.
     *
     * @param  string  $method
     * @return $this
     */
    public function via($method);

    /**
     * Run the pipeline with a final destination callback.
     *
     * @param  \Closure  $destination
     * @return mixed
     */
    public function then(Closure $destination);
}

基本操作就4个send,through,via,then ,一个常见的应用是

$pipeline->send($request)->through($middles)->then($handle);

非常直观的语义,在看实现之前,我们先自己来实现下这个功能

3. 动手实现

在实现之前,我们先看下下面一段代码

function foldLeft($f, $zero, array $list) {
    if(empty($list)){
        return $zero;
    }
    else {
        $head = array_first($list);
        $tails = array_slice($list,1);
        return foldLeft($f,$f($zero,$head),$tails);
    }
}
class PipelineTest extends \PHPUnit_Framework_TestCase{

    public function testFoldLeft()
    {
        $arr = range(1,10);
        $sum = foldLeft(function($a,$b){
            return $a + $b;
        },0,$arr);
        $this->assertEquals(55,$sum);
    }
}

上面功能很简单,通过foldLeft函数,实现了数组求和,函数foldLeft 有3个参数,第一个是一个二元函数,第二个是一个初值,第三个则是需要操作的集合,组合起来可以通过一张图来说明:

foldLeft

让我们对foldLeft函数更进一步,看下他的函数类型

foldLeft :: (b -> a -> b) -> b -> t a -> b

此处(b -> a -> b)是函数$f的类型,根据上面的定义,如果我们现在数组t a中元素a都是函数,而类型b也是函数,这样子的话,此处a相当于于处理对象的middle ware,而b是具体的处理对象的函数,这样子讲可能比较抽象,让我们看下下面的例子:

public function testFoldLeftFunc()
    {
        $arr = [
            function($a, $stack){
                return $stack($a . " 1 ");
            },
            function($a, $stack){
                return $stack($a . " 2 ");
            },
            function($a, $stack){
                return $stack($a . " 3 ");
            },
        ];
        //foldl :: (b -> a -> b) -> b -> t a -> b
        $result = foldLeft(function($stack,$item){
            return function($pass) use ($stack, $item){
                return call_user_func($item,$pass,$stack);
            };
        },function( $pass ){
            return array("zero"=>$pass);
        },array_reverse($arr));
        $res = call_user_func($result,"finial value");
        $this->assertEquals(["zero" => "finial value 1  2  3 "],$res);
    }

具体来说就是对于$arr中的函数,我们依次应用到finial value后,最终调用function( $pass ){ return array("zero"=>$pass);}

看完上面的例子后,我们再来看下Laravel中Pipeline的实现,就会发现简单很多

4. Laravel中Pipeline实现

public function then(Closure $destination)
    {
        //!! 返回一个闭包,参数为 $passable=$request
        $firstSlice = $this->getInitialSlice($destination);
        //!! 翻转数组,后来的条件先调用
        $pipes = array_reverse($this->pipes);

        return call_user_func(
            //!! 函数是编程,以$firstSlice为初始值,对$pipes挨个调用$this->getSlice()
            //!! $this->getSlice()返回的函数接受两个参数($stack, $pipe)
            //!! 其中$pipe是$pipes中的单个函数,$stack是$this->getSlice()函数处理完后的值
            array_reduce($pipes, $this->getSlice(), $firstSlice), $this->passable
        );
    }··

上面的getInitialSlice函数即我们的$zero,而getSlice则是(b -> a -> b),具体两个函数的实现可以去看下Laravel,原理就是第3节讲的。

5. 总结

Pipeline可以方便我们应用一系列中间函数到要处理的对象,如果其中某一个中间处理函数失败,我们可以抛出异常,我们可以看到Laravel中好多地方都用到了Pipeline,是非常基础的功能。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-day03-基础题

Java基础-day03-基础题 1.Scanner类,练习案例 Test1,定义main()方法,按以下步骤编写代码: A.导入Scanner类; B.在ma...

32950
来自专栏ml

NYOJ-------表达式求值

时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求...

404100
来自专栏前端架构与工程

JavaScript递归中的作用域问题

需求是这样的,从子节点寻找指定className的父节点,一开始就想到递归(笨!),Dom结构如下: <div class="layer_1"> <di...

18980
来自专栏行者常至

003.python科学计算库pandas(上)

版权声明:本文为博主原创文章,允许转载,请标明出处。 https://blog.csdn.net/qwdafedv/article/deta...

10520
来自专栏五分钟学算法

每天一算:Reverse Linked List

24710
来自专栏从流域到海域

《笨办法学Python》 第5课手记

《笨办法学Python》 第5课手记 本节内容复习了前两节的内容,并且引入了格式化字符,这节课里的格式化字符与C语言格式化字符,规则没有什么区别。 我把原文代码...

28290
来自专栏机器学习入门

LWC 63: 750. Number Of Corner Rectangles

LWC 63: 750. Number Of Corner Rectangles 传送门:750. Number Of Corner Rectangles Pr...

26170
来自专栏小樱的经验随笔

POJ 3278 Catch That Cow(BFS,板子题)

Catch That Cow Time Limit: 2000MS Memory Limit: 65536K Total Submissions...

32850
来自专栏Hongten

让你一看就明白什么是聚合-java版本_源码下载

=================================================

29030
来自专栏专注 Java 基础分享

漫谈计算机编码

我们知道,在计算机内部,所有的信息都是以二进制形式进行存储。无论是字符,或是视频音频文件,最终都会对应到一串由 0 和 1 构成的数字串。所以从我们能看懂的人类...

41360

扫码关注云+社区

领取腾讯云代金券