Laravel中实现中间件的方式:array_reduce方法详解

Laravel中实现中间件的方式主要是应用了 array_reduce方法,下面看代码示例,一个简化版的laravel中间件实现原理​


<?php
interface Middleware
{
    public static function handle($next);
}

class VerifyCSRFToken implements Middleware
{
    public static function handle($next)
    {
        echo "检查token";
        echo "<br>";
        $next();
    }
}

class SetSession implements Middleware
{
    public static function handle($next)
    {
        echo "设置session";
        echo "<br>";
        $next();
    }
}

class OrderSend implements Middleware
{
    public static function handle($next)
    {
        echo "发送订单";
        echo "<br>";
        $next();
    }
}

$arr = [
    'VerifyCSRFToken',
    'SetSession',
    'OrderSend'
];

$ctrlMethod = function () {
    echo "最终执行的控制器方法";
};

$r = array_reduce(array_reverse($arr), function ($ret, $item) {
    return function () use ($ret, $item) {
        return $item::handle($ret);
    };
},$ctrlMethod);

call_user_func($r); 
// 输出结果
//检查token
//设置session
//发送订单
//最终执行的控制器方法

伪代码推理:

1.第一次进行循环的时候 $ret = $ctrlMethod,$item = 'VerifyCSRFToken',那么第一次循环的结果就是

$firstLoop = function () use ($ret, $item) {
    return VerifyCSRFToken::handle(function () {
	echo "最终执行的控制器方法";
    })
}

2.第二次循环的时候 $ret = $firstLoop

$secondLoop = function () use ($ret, $item) {
    return SetSession::hanlde(function () use ($ret, $item) {
	return VerifyCSRFToken::handle(function () {
	    echo "最终执行的控制器方法";
	});
    });
}

3.第三次循环的时候 $ret = $secondLoop

$thirdLoop = function () use ($ret, $item) {
    return OrderSend::handle(function () use ($ret, $item) {
	return SetSession::hanlde(function () use ($ret, $item) {
	    return VerifyCSRFToken::handle(function () {
		echo "最终执行的控制器方法";
	    });
        });
    });
}

三次循环之后变成了这种结构,但是大家发现什么问题了没有,我在调用 $thirdLoop的时候,输出顺序是反过来的,也就是会先 OrderSend::handle(), 然后SetSession::handle() , 然后VerifyCSRFToken::handle(), 所以我们在使用这个中间件方式的时候,要首先对要通过的中间件进行翻转,这也就是为什么传递的第一个数组要先array_reverse翻转一下数组的原因 !!!