laravel middleware 之 array_reduce 详解
array_reduce() 将回调函数 callback 迭代地作用到 array 数组中的每一个单元中,从而将数组简化为单一的值。
www.php.net/manual/zh/function.arr...
<?php
$array = [
'middleware1',
'middleware2',
'middleware3',
];
$callback = function ($strack, $item) {
return $strack . '-' .$item;
};
$initial = 'initial';
$res = array_reduce($array, $callback, $initial);
print_r($res); // "initial-mdware1-mdware2-mdware3"
第一次迭代
第二次迭代
第三次迭代
数组迭代完毕返回最后的栈结果 "initial-mdware1-mdware2-mdware3"
,如果迭代的数组为空,则为初始栈 "initial"
,如果 array_reduce
第三个参数不填写,则初始栈为 null
。
此时仅仅是字符串相加,在 laravel 中的中间件自然都是功能体,功能体的意思是要么是闭包、要么是类的方法,我们将上边例子中的字符串全部换成功能体 :闭包。
<?php
$array = [
function($next) {
echo "mdware1";
$next();
},
function ($next) {
echo "mdware2";
$next();
},
function ($next) {
echo "mdware3";
$next();
},
];
$callback = function ($strack, $item) {
return $item($strack);
};
$initial = function() {
echo 'initial';
};
$res = array_reduce($array, $callback, $initial);
print_r($res);
此时我们简单的认为中间件这样编写
function($next) {
echo "mdware1";
$next();
}
即可以把上一次的栈包含到自己的功能体中,并且晚于 echo "mdware1"
调用,便实现了中间件的效果。但是出现一个问题,第一次迭代时 callback
方法中的 return $item($strack)
返回的栈是这样
function($next) {
echo "mdware1";
$next();
}(
function() {
echo 'initial';
}
)
结果是直接调用了,输出的栈是字符串 "mdware1initial"
,代表已经输出响应了,无法下一次迭代。
所以每次迭代返回的栈还应该是一个功能体,不能提前调用,因此改造 callback
如下:
$callback = function ($strack, $item) {
return function() use ($strack, $item) {
return $item($strack);
};
};
思考点:为什么是
use
而不是function($strack, $item)
。
这样则返回的栈是一个闭包,其代码并未调用。但值得注意的是 $strack, $item
保存了当前的状态,这正是利用了闭包的特性。
这个栈只需调用
function() use ($strack, $item) {
return $item($strack);
}()
就可以输出结果 "mdware1initial"
。
但迭代还未结束,当迭代完成后的最后一个栈,然后我们 栈()
调用就可以了。
整个 array_reduce
调用完毕后返回闭包
function() use ($strack, $item) {
return $item($strack);
}
此时闭包保存的变量状态为: $strack
为第二个栈,$item
是 mdware3
⌈不理解的话看上图,因最后一次迭代是 mdware3,上一次迭代的栈是其参数⌋。$item($strack)
即调用时代码如下:
function ($next) {
echo "mdware3";
$next();
}(栈2),
栈2
仍是一个闭包,$next()
即 栈2()
function() use ($strack, $item) {
return $item($strack);
}()
但其闭包保存的变量状态为: $strack
为第一个栈,$item
是 mdware2
,即调用时代码如下:
function ($next) {
echo "mdware2";
$next();
}(栈1)
栈1
仍是一个闭包,$next()
即 栈1()
function() use ($strack, $item) {
return $item($strack);
}()
但其闭包保存的变量状态为: $strack
为初始栈,$item
是 mdware1
,即调用时代码如下:
function($next) {
echo "mdware1";
$next();
}(function(){
echo "initial";
})
最后将完整代码贴下
<?php
$array = [
function($next) {
echo "mdware1.." . PHP_EOL;
$next();
},
function ($next) {
echo "mdware2" . PHP_EOL;
$next();
},
function ($next) {
echo "mdware3" . PHP_EOL;
$next();
},
];
$callback = function ($strack, $item) {
$cb = function() use ($strack, $item) {
return $item($strack);
};
return $cb;
};
$initial = function() {
echo 'initial' . PHP_EOL;
};
$res = array_reduce($array, $callback, $initial);
print_r( $res() );
PS D:\MyCode\study\php\code> php 1.php
mdware3
mdware2
mdware1..
initial
可能此时有人注意了,mdware
执行是反的,这是因为最先迭代的是最内层的,因此我们把 $array
array_reverse()
反转下就可以了。
本作品采用《CC 协议》,转载必须注明作者和本文链接