laravel的middleware中间件,使用了管道(pipe)。
什么是管道呢?
管道类似水净化过程中的层层过滤。
中间件的意思就是说,在接下来的逻辑之前,需要的操作。
例如江河之水我们不能直接喝,在输出净水之前新增了过滤细菌的机器。
那么我们把输出净水的逻辑,封装成一个匿名函数$next,然后只需要这样:
$next = function(){
//输出净水
}
$next2 = function($next){
echo 过滤细菌..
$next()
}
执行:
$next2()
输出:
//过滤细菌
//输出净水
现在发现水里有细沙,我们又引入了过滤细沙的机器,需要在目前过滤系统的之前执行。
$next3 = function($next2){
echo 过滤细沙
$next2()
}
执行:
$next3();
输出:
//过滤细沙
//过滤细菌
//输出净水
到这里,可能理解起来不是很容易,上边就是常说的装饰者模式。不妨再举个现实中的例子。比如一个公司,经理–>部门经理–>组长–>员工,员工要发布一个新闻稿,在她定稿之前,需要向组长请示,组长补充意见后,需要向部门经理请示,部门经理补充意见后,再向总经理请示,总经理补充意见后,才能正式定稿。
中间件的示例代码
$step1 = function ($next){
echo "第一步:过滤小石头".PHP_EOL;
$next();
};
$step2=function ($next){
echo "第二步:过滤细沙".PHP_EOL;
$next();
};
$step3 = function ($next){
echo "第三步:过滤细菌".PHP_EOL;
$next();
};
$sucess = function (){
echo "最后:输出纯净水".PHP_EOL;
};
$callback = function ($next,$step) {
return function () use ( $next, $step ) {
return $step($next);
};
};
$middleWares = [
$step1,
$step2,
$step3
];
$middleWares=array_reverse($middleWares); //将数组元素顺序反转
call_user_func(
array_reduce($middleWares,$callback,$sucess)
);
//第一步:过滤小石头 第二步:过滤细沙 第三步:过滤细菌 最后:输出纯净水
array_reduce
laravel的中间件,用了一个很重要的php函数 array_reduce
array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed
array_reduce() 将回调函数 callback 迭代地作用到 array 数组中的每一个单元中,从而将数组简化为单一的值。
注:解释挺拗口的,不妨看下官方给的例子理解下
function callback($carry, $item){
$carry += $item;
return $carry;
}
$a = array(1, 2, 3);
array_reduce($a, "callback")); //6
这个函数将数组里的每个值,依次带入callback函数的item参数,然后将返回值作为第一个参数$carry
,例如先将1带入callback($carry,1)
(第一次$carry
的值就是该函数第三个参数$initial
),返回1。然后将1赋值给$carry
,当再把2带入callback()时,变成callback(1,2)
,返回3。再把3赋值给carry,继续将$a数组中的3
带入callback(),变成callback(3,3)
最后结果是6。
即将array中的每个值,依次被自定义函数处理,官方的例子是执行array数组的元素相加的逻辑,最终返回单一的值。
array(4,5,6)
4—callback()—>4
5—callback()—>4+5—>9
6—callback()—>9+6—>15
模拟laravel中间件
当然laravel中的中间件是一个一个实现了接口的类。
interface MiddleWare{
public static function handle(Closure $next);
}
class StartSession implements MiddleWare{
public static function handle( Closure $next ) {
echo '开启 session'.'<br>';
$next();
echo '关闭 session'.'<br>';
}
}
class AddQueuedCookiesToResponse implements MiddleWare{
public static function handle( Closure $next ) {
$next();
echo '添加下一次请求的token'."<br>";
}
}
class EbcryptCookies implements MiddleWare{
public static function handle( Closure $next ) {
echo '对 cookie 加密'.'<br>';
$next();
echo '对 cookie 解密'.'<br>';
}
}
function getSlice(){
return function ($stack,$pipe){
return function () use ($stack,$pipe){
return $pipe::handle($stack);
};
};
}
function then() {
$pipes = [
'EbcryptCookies', //加密请求cookie
'AddQueuedCookiesToResponse', //添加下一次请求需要的cookie
'StartSession', //开启session
];
$firstSlice=function(){echo '请求向路由器传递,返回相应'.'<br>';};
$pipes=array_reverse($pipes);
call_user_func(
array_reduce($pipes,getSlice(),$firstSlice)
);
}
then();
/*
对 cookie 加密
开启 session
请求向路由器传递,返回相应
关闭 session
添加下一次请求的token
对 cookie 解密
*/