Tp5.1也引入了中间件的功能

中间件使用

1.定义中间件类

框架可以使用它命令或者自己在application/http/middleware目录下面生成一个Check中间件,格式一定要如下:必须有handle方法,第一个参数必须是Request对象,第二个是闭包。

class Check
{public function handle(Request $request, \Closure $next){$request->name = 'aaaaa';return $next($request); //执行$next闭包函数,并且把这个闭包函数的结果return。}
}

中间件的handle方法就是执行自己的代码,然后调用执行下一个中间件的代码。 结合后面的解析,我们知道$next就是通过Middleware::resolve()返回的闭包函数。这个闭包函数的执行就是从中间件队列中弹出一个中间件,然后通过call_fun_array()执行这个中间件的handle方法。所以中间件的return其实是执行最后一个中间件的return结果。

后置中间件

class After
{public function handle(Request $request, \Closure $next){$response = $next($request);//todo 执行后置中间件的代码return $response;}
}

2.注册中间件

1.在路由上注册(只有这个路由才会走中间件)

传'Check',会自动在application/http/middleware目录下找到Check类,也可以传完整类名

Route::get('test', 'Demo/dbTest')->middleware('Check');

2.在对应的目录模块上注册 (这个目录下的控制器方法都会走中间件)tp5.1.8+

例如在application目录下新建middleware.php,则全局都会走这个中间件,如果在application\admin目录下建middleware.php,则只有admin模块下的控制器才会走中间件。

return ['Check', //没有写类全名,默认在application/http/middleware下找中间件
];

3.在对应控制器注册中间件(只有这个控制器的方法才走)tp5.1.17+

控制器需要继承系统的think\Controller类,然后在控制器中定义middleware属性,例如

namespace app\index\controller;use think\Controller;
class Index extends Controller
{protected $middleware = ['check'];public function test(){}
}

中间件原理 (Middleware类)

think\Middleware类重要属性

$queue = [],存放中间件的数组

$config = [],存放中间件的配置信息

think\Middleware类重要方法

1.buildMiddleware($middleware, $type = 'route'),$middleware可以是‘check’,check的类名,或者闭包。

//如果$middleware是闭包
if ($middleware instanceof \Closure) {return [$middleware, isset($param) ? $param : null];}
//如果是'check',会去拼接到全类名
return [[$this->app->make($middleware), 'handle'], isset($param) ? $param : null];

2.add()把解析好的中间件挂到属性$queue. 一个中间件元素的格式是[['中间件对象',‘handle’], $param];或者[闭包,$param];

$middleware = $this->buildMiddleware($middleware, $type);
if ($middleware) {$this->queue[$type][] = $middleware;
}

并且以$type区分开,$type默认是‘route’;

3.dispatch(Request $request, $type = 'route')中间件调度,就是执行resolve返回的闭包函数

//就是按照一定顺序执行中间件
public function dispatch(Request $request, $type = 'route'){return call_user_func($this->resolve($type), $request);}

4.resolve($type),返回闭包函数,这个闭包函数就是handle方法中的$next。

protected function resolve($type = 'route'){return function (Request $request) use ($type) {$middleware = array_shift($this->queue[$type]);            list($call, $param) = $middleware;try {$response = call_user_func_array($call, [$request, $this->resolve($type), $param]);} catch (HttpResponseException $exception) {$response = $exception->getResponse();}if (!$response instanceof Response) {throw new LogicException('The middleware must return Response instance');}return $response;};}

如何执行中间件的handle方法的,call_user_func_array(),最终得到某个中间件的返回值。并且返回值必须是Response对象,不然会包错。

//这个就是执行中间件的handle方法,而handler方法最后又会执行resolve返回的闭包方法,
//相当于又得到另外一个$call再次执行下面这段代码。所以这是一个递归的过程。
//一直循环到某个中间件,没有再调用$this->resolve($type)这个闭包参数。即在handle方法中没有执行$next($resquest);而是直接返回Response对象。然后一层一层往上归回来。
$response = call_user_func_array($call, [$request, $this->resolve($type), $param]);$call就是[中间件对象,'handle']
$request就是handle的第一个参数
$this->resolve($type),就是handle的第二个参数,是一个闭包
$param是第三个参数
$response就是handle的返回值

TP5.1是如何使用Middleware类库实现中间件的功能的

1.初始化模块init(),会加载模块目录下的middleware.php文件

 // 加载中间件文件,import没有传type,默认是routeif (is_file($path . 'middleware.php')) {$middleware = include $path . 'middleware.php';if (is_array($middleware)) {$this->middleware->import($middleware);}}

初始化模块方法init(),在系统初始化的时候调用一次,那时候还没有解析路由,默认模块就是Application模块,然后根据访问路径得到模块,然后会再次调用,表示初始化对应模块。所以一个进程只会加载Application/和访问模块的下的middleware.php。

2. 路由文件导入,include rute目录下的文件。

//get方法返回的是RuleItem实例,我们知道一条路由规则生成一个RuleItem实例。
Route::get('test', 'Demo/test')->middleware('Check');

middleware方法会把Check放到属性option中,在创建调度对象Module实例前,会把中间件加进去

 // 添加域名中间件
if (!empty($this->option['middleware'])) {Container::get('middleware')->import($this->option['middleware']);unset($this->option['middleware']);}

3.调度器执行方法,作为一个匿名函数,加入到中间件队列中

//通过路由解析后,最终通过$dispatch->run()其实就是执行我们的控制器方法,然后返回Response对象。
//正常路由解析后,$data为null。
$this->middleware->add(function (Request $request, $next) use ($dispatch, $data) {return is_null($data) ? $dispatch->run() : $data;});
//中间件调度,把注册好的中间件按顺序执行,直到执行到返回Response对象的那个中间件
$response = $this->middleware->dispatch($this->request);

上面三种方式,分别把middleware.php的中间件,自定义路由的中间件,控制器的执行分别加入到中间件队列。

PHP的Closure类

我们创建一个闭包函数,var_dump这个闭包函数,发现他是一个Closure类。在PHP中定义一个闭包函数其实就是一个Closure类的实例。闭包函数作为函数参数,可以看做是把这段函数代码传给函数。

TP5.1中间件的使用相关推荐

  1. oracle中间件微信公众号,对TP5.1中间件融合微信公众号代码的优化

    总结: 在上一篇文章中,我们使用了中间节对echostr的验证是起不到验证的作用的 这一篇我们对代码进行稍微的改动下图 1.中间件代码优化版本 /* author:咔咔 wechat:fangkang ...

  2. 中间件方法必须返回Response对象实例(tp5.1+小程序结合时候出的问题)

    前言:在最近开发小程序通过中间件检查是否携带token时候报的一个错误 解决方法: 根据手册中需要return出去才可以不报错 转载于:https://www.cnblogs.com/learning ...

  3. thinkphp5.1 中间件是什么有什么用

    中间件是什么?有什么作用? 中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理.---tp5.1手册 也就是说,降低了系统的耦合:[在http请求阶段,执行中间件的入口执行方法(hand ...

  4. tp5 mysql实现消息队列_TP5系列 | Queue消息队列

    消费信息如下ThinkPHP5 Queue消息队列 优点 1.Queue内置了 Redis,Database,Topthink ,Sync这四种驱动,本文使用Redis驱动 2.Queue消息队列适用 ...

  5. tp5与tp6的区别是啥呀?

    1 目录结构的异同 tp5核心框架是项目根目录thinkphp下 , tp6是vendor的topthink 2 安装方式不同,tp6仅能通过composer方式安装 3 类自动加载方式不同 tp6使 ...

  6. Laravel 中管道设计模式的使用 —— 中间件实现原理探究

    所谓管道(Pipeline)设计模式就是将会数据传递到一个任务序列中,管道扮演者流水线的角色,数据在这里被处理然后传递到下一个步骤. 使用管道使用很多好处的,尤其是在单个任务中编写复杂处理代码时管道为 ...

  7. thinkphp5.1中间件是什么,有什么用

    中间件是什么?有什么作用? 中间件主要用于拦截或过滤应用的HTTP请求,并进行必要的业务处理. 也就是说,降低了系统的耦合:[在http请求阶段,执行中间件的入口执行方法(handle)–tp5.1] ...

  8. tp5和tp6版本之间的差异

    TP5主要特性: 规范:遵循PSR-2.PSR-4规范,Composer及单元测试支持: 严谨:异常严谨的错误检测和安全机制,详细的日志信息,为你的开发保驾护航: 灵活:减少核心依赖,扩展更灵活.方便 ...

  9. TP5.1钩子的实现以及TP6.0事件的原理

    TP框架的钩子功能很早就有了,tp5.1对它的实现又重新构造了,钩子的功能其实就是在代码中侵入其他代码流程.比如在初始化完后监听一个钩子,如果我们注册了这个钩子,并且绑定了一个行为,执行到这里的时候会 ...

最新文章

  1. 【C++】C++11 STL算法(六):最小/最大操作(Minimum/maximum operations)、比较运算(Comparison operations)
  2. 清华数为DWF低代码平台亮相2021全球数字经济大会
  3. 做产品最怕得是没有人负责
  4. Linux环境下使用dosemu写汇编
  5. python提取图片文字视频教学_用Python提取视频中的图片
  6. Vue系列:通过vue-router如何传递参数
  7. Nodejs写的搬家工具知识分享
  8. 会考计算机考试模拟软件,计算机会考考试模拟(范文).doc
  9. 如何设计一个好看的 404 错误页面 ?
  10. kindeditor 上传图片 php,Kindeditor编辑器添加图片上传水印功能(php代码)
  11. Java Date总结
  12. 计算机怎么切换到音乐,win10系统如何快速切换到下一首歌曲?
  13. tf.maximum
  14. 动态规划 - 切钢条 (python)
  15. VMware虚拟机备份和恢复
  16. Redis--Redis数据过期策略详解
  17. 判断map的key的value是否为空
  18. php转mp3的工厂,魔影工厂怎么转成mp3 魔影工厂转换mp3教程
  19. HTML元素居中定位与尺寸拉伸
  20. mac系统python读取文件路径_python读取文件常见问题(Mac版)

热门文章

  1. ubuntu 18.04 安装 synergy 局域网内公用一个鼠标键盘、TeamViewer
  2. C++ 中对浮点数的输出控制
  3. CSS动画制作绽放的花朵
  4. SpringBoot项目集成logback日志分等级配置
  5. 《炬丰科技-半导体工艺》氮化栅氧化物的表面制备挑战
  6. 数据库|MySQL数据库基础(一)
  7. 1106:年龄与疾病
  8. 用AS编写一个简单计算器
  9. 更新Jetson TX2内核及dtb文件
  10. 游戏配音如何提高声音感知力