Laravel请求处理管道理解
必备知识点:
闭包(Closure)、array_reduce()函数、array_reverse()函数、call_user_func()函数
装饰者模式
资料:
《Laravel框架关键技术解析》
相关博客
示例代码:
interface Middleware
{
public static function handle(Closure $next);
}
class VerifyCsrfToken implements Middleware
{
public static function handle(Closure $next)
{
echo "验证 CSRF Token<br />";
$next();
}
}
class ShareErrorsFromSession implements Middleware
{
public static function handle(Closure $next)
{
echo "如果 Session中有'errors'变量, 则共享它<br />";
$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 "添加下一次请求需要的cookie".'<br>';
}
}
class EncryptCookies implements Middleware
{
public static function handle(Closure $next)
{
echo "对输入 Cookie 进行解密<br />";
$next();
echo "对输出 Cookie 进行加密";
}
}
class CheckMaintenanceMode implements Middleware
{
public static function handle(Closure $next)
{
echo "检测系统是否处于维护状态<br />";
$next();
}
}
function getSlice()
{
return function ($stack, $pipe) {
return function () use ($stack, $pipe) {
return $pipe::handle($stack);
};
};
}
function then()
{
$pipes = [
CheckMaintenanceMode::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
];
$firstSlice = function () {
echo "请求向路由器传递,返回响应<br />";
};
$pipes = array_reverse($pipes);
call_user_func(
array_reduce($pipes, getSlice(), $firstSlice)
);
}
then();
执行流程
- 刚开始执行,首先
array_reservse()
函数将$pipes
数组倒序反转,至于为什么需要反转后面再说明。 array_reduce()
将回调函数getSlice()
迭代地作用到$pipes
数组中的每一个单元中,而array_reduce()
设置了初始值,则第一个执行的是$firstSlice
这个函数。- 第一个执行的是
$firstSlice
这个函数,所以function ($firstSlice, VerifyCsrfToken::class) { return function ($firstSlice, VerifyCsrfToken::class) { return VerifyCsrfToken::handle($firstSlice); } }
- 执行到第二个是时候是
function (VerifyCsrfToken::class, ShareErrorsFromSession::class) { return function (VerifyCsrfToken::class, ShareErrorsFromSession::class) { return ShareErrorsFromSession::handle(function ($firstSlice, VerifyCsrfToken::class) { return function ($firstSlice, VerifyCsrfToken::class) { return VerifyCsrfToken::handle($firstSlice); } }); } }
- 以此类推….
最后变成这样:
执行到数组的最后一次,则是function (){ return CheckMaintenanceMode::handle(function (){ return EncryptCookies::handle(function (){ return AddQueuedCookiesToResponse::handle(function (){ return StartSession::handle(function (){ return ShareErrorsFromSession::handle(function (){ return VerifyCsrfToken::handle(function (){ echo "请求向路由器传递,返回响应<br />"; }) }) }); }); }); }); }
CheckMaintenanceMode::class
,然后call_user_func()
执行回调函数,先执行CheckMaintenanceMode::class
,然后执行EncryptCookies::class
,执行顺序则与未反转前的数组顺序完全相同,这也是为什么需要使用array_reservse()
函数进行反转的原因。执行结果
检测系统是否处于维护状态 对输入 Cookie 进行解密 开启 Session,获取会话数据 如果 Session中有'errors'变量, 则共享它 验证 CSRF Token 请求向路由器传递,返回响应 保存会话数据,关闭 Session 添加下一次请求需要的cookie 对输出 Cookie 进行加密
本作品采用《CC 协议》,转载必须注明作者和本文链接