企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 中间件实现代码 你一定听过Laravel中间件的概念跟装饰器模式很像.简单来讲,装饰器模式就是在开放-关闭原则下动态的增加或者删除某一个功能.而Laravel的中间件也差不多是这个道理: >一个请求过来,在执行请求之前,可能要进行Cookie加密,开启回话,CSRF保护等等操作.但是每一个请求不一定都需要这些操作,而且,在执行请求之后也可能需要执行一些操作.我们需要根据请求的特性动态的增加一些操作.这些需求正好可以使用装饰器模式解决. 但是,Laravel中的中间件在代码实现上跟中间件 又有点区别,这里给出一段代码.真实的模拟了Laravel中间件的工作流程. ~~~ <?php interface Middleware { public static function handle(Closure $next); } class VerfiyCsrfToekn implements Middleware { public static function handle(Closure $next) { echo '验证csrf Token', PHP_EOL; $next(); } } class ShowErrorsFromSession implements Middleware { public static function handle(Closure $next) { echo '共享session中的Error变量', PHP_EOL; $next(); } } class StartSession implements Middleware { public static function handle(Closure $next) { echo '开启session', PHP_EOL; $next(); echo '关闭session', PHP_EOL; } } class AddQueuedCookieToResponse implements Middleware { public static function handle(Closure $next) { $next(); echo '添加下一次请求需要的cookie', PHP_EOL; } } class EncryptCookies implements Middleware { public static function handle(Closure $next) { echo '解密cookie', PHP_EOL; $next(); echo '加密cookie', PHP_EOL; } } class CheckForMaintenacceMode implements Middleware { public static function handle(Closure $next) { echo '确定当前程序是否处于维护状态', PHP_EOL; $next(); } } function getSlice() { return function ($stack, $pipe) { return function () use ($stack, $pipe) { return $pipe::handle($stack); }; }; } function then() { $pipe = [ 'CheckForMaintenacceMode', //确定当前程序是否处于维护状态 前置 'EncryptCookies', //解密cookie 前置 加密cookie 后置 'AddQueuedCookieToResponse', //添加下一次请求需要的cookie 后置 'StartSession', //开启session 前置 关闭session 后置 'ShowErrorsFromSession', //共享session中error变量 前置 'VerfiyCsrfToekn', //csrf 前置 ]; $firstSlice = function () { echo '请求向路由传递,返回响应', PHP_EOL; }; //数组翻转 $pipe = array_reverse($pipe); //这一行,实现了管道和中间件的执行 $callback = array_reduce($pipe, getSlice(), $firstSlice); call_user_func($callback); } then(); ~~~ 运行代码,输出 >确定当前程序是否处于维护状态 解密cookie 开启session 共享session中的Error变量 验证csrf Token 请求向路由传递,返回相应 关闭ession 添加下一次请求需要的cookie 加密cookie 这段代码可能有点难懂,原因在于对于闭包函数(Closure),array_reduce以及call_user_fun函数,而且函数调用过程又是递归,可以尝试使用xdebug来调试执行.这里只提一点,array_reduce中第二个参数是一个函数,这个函数需要两个参数: * 第一个参数从array_reduce的第一个参数$pipe数组中获得 * 第二个参数为上一次调用的返回值.这个例子里面返回值是一个闭包函数