middleware 原理

middleware 的原理就是「管道」。

管道 (pipe)

管道类似水净化过程中的层层过滤。

middleware 原理

中间件的意思就是说,在接下来的逻辑之前,需要的操作。
例如江河之水我们不能直接喝,在输出净水之前有过滤细菌的机器。
那么我们把输出净水的逻辑,封装成一个匿名函数 $next,然后只需要这样:

$next = function(){
    echo "输出净水";
}
$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();
};

$success = 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,$success)
);
//第一步:过滤小石头 第二步:过滤细沙 第三步:过滤细菌 最后:输出纯净水

array_reduce

array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed
array_reduce() 将回调函数 callback 迭代地作用到 array 数组中的每一个单元中,从而将数组简化为单一的值。

解释挺不容易明白,$array就是中间件数组;$callback 见上面的 $callback 变量,永远返回一个闭包函数;$initial 意思是 init 初始值,也就是最终的目的「输出净水」$success

模拟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 解密
    */
本作品采用《CC 协议》,转载必须注明作者和本文链接
welcome come back
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 4

实例代码最后一段有个小错误,应该是:

call_user_func(
    array_reduce($middleWares,$callback,$success )
);

success写错了

3年前 评论
php_yt (楼主) 3年前
jcc123

很直观

3年前 评论
pndx

收藏了,感觉弄懂了这个会很有用

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
94
粉丝
24
喜欢
156
收藏
346
排名:325
访问:2.9 万
私信
所有博文
社区赞助商