请求处理管道个人理解
学前必备知识点:闭包(Closure),array_reduce(),array_reverse()
可选进阶知识点:装饰者模式
简易模拟请求处理管道
<?php
/**
* Interface Step
*/
interface Step {
/**
* @param Closure $next
* @return mixed
*/
public static function go(Closure $next);
}
/**
* 中间件1
* Class FirstStep
*/
class FirstStep implements Step {
/**
* @param Closure $next
*/
public static function go (Closure $next)
{
echo "开启session,获取数据...".'<br>';
$next();
echo "保存数据,关闭SESSION...".'<br>';
}
}
/**
* 中间件2
* Class SecondStep
*/
class SecondStep implements Step {
/**
* @param Closure $next
*/
public static function go(Closure $next)
{
echo "检测用户权限";
$next();
}
}
/**
* array_reduce自定义函数
* @param $step
* @param $className
* @return Closure
*/
function goFun($step, $className)
{
return function() use($step,$className)
{
return $className::go($step);
};
}
/**
* 模拟执行处理管道
*/
function then()
{
$steps = ["FirstStep","SecondStep"];
$prepare = function() { echo "请求向路由器传递,返回响应...".'<br>';};
$go = array_reduce($steps,"goFun",$prepare);
//这里是关键,第一个是要处理的数组,第二个是自定义回调函数,
//第三个是可选参数,为初始化参数,被当作array_reduce中第一个值来处理,若数组为空则作为返回值。
//var_dump($go);
//$test = new Reflection($go);
$go();
}
then();
/*
* 详细解析
* 定义步骤一,步骤二
* 定义初始化参数$preapres
* array_reduce执行过程:
* 1.生成闭包函数function()
{
FirstStep::go($prepares);
};
* 2.生成function()
{
SecondStep::go(function()
{
FirstStep::go($prepares);
};);
};
* 最终执行顺序是每个类中的go方法:SecondStep,First的第一个步骤,$prepares,First的第二个步骤,可以看到与数组['FirstStep,'SecondStep']的顺序反过来了
* 在实际Laravel的管道中用了array_reverse,使得执行顺序与数组定义的顺序一致
* 这里看起来有点类似递归,先一层一层进入,再把执行权一层一层转回去
在闭包中传入闭包…..
执行闭包 , 在闭包的语句里再执行传入的闭包
* */
laravel中的请求处理管道
<?php
interface Middleware
{
public static function handle(Closure $next);
}
class VerifyCsrfToken implements Middleware
{
public static function handle(Closure $next)
{
echo "验证csrf-token.......";
$next();
}
}
class ShareErrorsFromSession implements Middleware
{
public static function handle(Closure $next)
{
echo "如果session中有errors变量,共享他....";
$next();
}
}
class StartSession implements Middleware
{
public static function handle(Closure $next)
{
echo "开启session,获取数据....";
$next();
echo "保存数据,关闭session..";
}
}
class AddQueuedCookiesToResponse implements Middleware
{
public static function handle(Closure $next)
{
$next();
echo "添加下一次请求需要的cookie...";
}
}
class EncryptCookies implements Middleware
{
public static function handle(Closure $next)
{
echo "对输入请求的cookie进行解密...";
$next();
echo "对输出响应的cookie进行加密...";
}
}
class CheckForMaintenanceMode implements Middleware
{
public static function handle(Closure $next)
{
echo "确定当前程序是否处于维护状态...";
$next();
}
}
function getSlice()
{
return function ($stack, $pipe) {
return function () use ($stack, $pipe) {
return $pipe::handle($stack);
};
};
}
function then()
{
$pipes= [
"CheckForMaintenanceMode",
"EncryptCookies",
"AddQueuedCookiesToResponse",
"StartSession",
"ShareErrorsFromSession",
"VerifyCsrfToken"
];
$firstSlice = function () {
echo "请求向路由器传递,返回响应....";
};
$pipes = array_reverse($pipes);
call_user_func(
array_reduce($pipes, getSlice(), $firstSlice)
);
}
then();
/*
* 先reverse把数组倒转过来
* 于是先生成VerifyCsrfTokenLLhanle($firstSlice);
* 再生成ShareErrorsFromSession::handle($上一步生成的闭包);
* ......
* ....
* 最后生成CheckForMaintenanceMode::handle($上一步生成的闭包);
*
* 于是执行顺序就变为脑图
*
*/
本作品采用《CC 协议》,转载必须注明作者和本文链接
laravel 框架关键技术解析 ? :joy:
@KevinYang 对 :joy: 好书