array_reduce php

最近一直在看tp6的源码,运行逻辑,然后一直卡到了中间件运行的部分。

$pipeline = array_reduce(
            array_reverse($this->pipes),
            $this->carry(),
            function ($passable) use ($destination) {
                try {
                    return $destination($passable);
                } catch (Throwable | Exception $e) {
                    return $this->handleException($passable, $e);
                }
            }
        );
array_reverse里面装的全是闭包然后传入了定义时的中间件名称,然后把闭包参数传给 $this->carry()方法
 protected function carry()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                
                try {
                    return $pipe($passable, $stack);
                } catch (Throwable | Exception $e) {
                    return $this->handleException($passable, $e);
                }
            };
        };
    }

array_reduce 第一个参数是一个数组,第二个参数是一个方法,第三个参数是一个默认值

因为第二个参数每次会调用2个参数 第一个参数为上一次调用的结果,第二个参数为当前数组值

$testArr=[1,2,3];

function test($first , $two){
    return $first+$two;
}

//array_reduce的每次调用就是

test(null,1);

test(null+1,2);

test(null+1+2,3);

//如果有第三个参数假设为 5

test(5,1);

test(5+1,2);

test(5+1+2,3);

也就是将上一次的结果继续做下次运算。

而tp6里的第一个参数装载的都是闭包(Closure)

  return function ($request, $next) use ($middleware) {
                    [$call, $params] = $middleware;
                    if (is_array($call) && is_string($call[0])) {
                        $call = [$this->app->make($call[0]), $call[1]];
                    }
                    $response = call_user_func($call, $request, $next, ...$params);

                    if (!$response instanceof Response) {
                        throw new LogicException('The middleware must return Response instance');
                    }
                    return $response;
                };

$middleware 指向的就是用户定义和tp6自定义的中间件地址

这个闭关会去调用中间件地址的handle方法(解析中间件的时候默认指定的handle方法)

protected function carry()
    {
        return function ($stack, $pipe) {
            return function ($passable) use ($stack, $pipe) {
                
                try {
                    return $pipe($passable, $stack);
                } catch (Throwable | Exception $e) {
                    return $this->handleException($passable, $e);
                }
            };
        };
    }

这就对所有闭关进行了一个嵌套,每当你运行当前函数时候都会把上一个闭包当参数传递进来。运行的时候感觉就是这样的不知道对不对。


$default=function(){
    echo 'default<br>';

};
$a=function($next){
    return function()use($next){
         echo 'a<br>';
         $next();
    };
};
$b=function($next){
    return function()use($next){
        echo 'b<br>';
        $next();
    };
};
$c=function($next){
    return function()use($next){
        echo 'c<br>';
        $next();
    };
};


$p = $c($b($a($default)));
$p();

/*
结果:
c
b
a
default



*/

具体在default前面还是后面 就看你调用next()的是在你输出前还是后面。

由于array_reduce运行数组是从左到右,但是暴露出来的结果一定是最上层的(最右边)所以对数组进行反转(array_reverse) ,那么运行的结果就是先执行Test中的handel方法然后执行TestTwo中的handle。

//middleware配置文件
app\middleware\Test::class,
app\middleware\TestTwo::class,

//Test Class
namespace app\middleware;

class Test{

    public function handle($request,$next){
        echo 1;
        return $next($request);
    }
}


//TestTwo Class
namespace app\middleware;

class TestTwo{

    public function handle($request,$next){
        echo 2;
        return $next($request);
    }
}

//对于之前已经装载好的闭包其实就是
/*
//$request是之前示例好的对象
//闭包最里层装载的tp的初始化的东西返回是response对象
$one = function ($request) {
       return $this->dispatchToRoute($request);
}
//这里就相当于自己运行的方法了
$testTwoHandle = function($request,$next){
    echo 2;
    return $next($request); 
}
testHandle($request,$next){
    echo 1;
    return $next($request);
}
testHandle($request,$testTwoHandle );


*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值