前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Laravel之Pipeline1. 背景2. 基本操作3. 动手实现4. Laravel中Pipeline实现5. 总结

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

作者头像
zhuanxu
发布2018-08-23 12:47:00
3970
发布2018-08-23 12:47:00
举报
文章被收录于专栏:进击的程序猿进击的程序猿

1. 背景

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

2. 基本操作

代码语言:javascript
复制
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 ,一个常见的应用是

代码语言:javascript
复制
$pipeline->send($request)->through($middles)->then($handle);

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

3. 动手实现

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

代码语言:javascript
复制
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函数更进一步,看下他的函数类型

代码语言:javascript
复制
foldLeft :: (b -> a -> b) -> b -> t a -> b

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

代码语言:javascript
复制
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实现

代码语言:javascript
复制
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,是非常基础的功能。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.06.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 背景
  • 2. 基本操作
  • 3. 动手实现
  • 4. Laravel中Pipeline实现
  • 5. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档