简述 laravel中间件 的原理

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 解密
	*/

猜你喜欢

转载自blog.csdn.net/yt_php/article/details/86694276
今日推荐