slimphp中间件调用流程的理解
slimphp是一款微型php框架,主要是处理http请求,并调用合适的程序处理,并返回一个http响应。
它遵循php的psr7规范,可以很方便的集成其它遵循psr7规范的php组建。
当读到中间件时,官网给出了,如下所示的图
试验如下:
$mw1 = function ($request, $response, $next) {echo('middleware 1 start <br>');$response = $next($request, $response);echo('middleware 1 end <br>');return $response; };$mw2 = function ($request, $response, $next) {echo('middleware 2 start <br>');$response = $next($request, $response);echo('middleware 2 end <br>');return $response; };$app->get('/mw', function ($request, $response, $args) {echo(' Hello <br>');return $response; })->add($mw1)->add($mw2);
输出为:
middleware 2 start
middleware 1 start
middleware 1 end
middleware 2 end
Hello
于是开始调试跟踪,发现原来如此:
在vendor\slim\slim\Slim\MiddlewareAwareTrait.php里有如下代码:
protected function addMiddleware(callable $callable) {if ($this->middlewareLock) {throw new RuntimeException('Middleware can’t be added once the stack is dequeuing');}if (is_null($this->stack)) {$this->seedMiddlewareStack();}$next = $this->stack->top();$this->stack[] = function (ServerRequestInterface $req, ResponseInterface $res) use ($callable, $next) {$result = call_user_func($callable, $req, $res, $next);if ($result instanceof ResponseInterface === false) {throw new UnexpectedValueException('Middleware must return instance of \Psr\Http\Message\ResponseInterface');}return $result;};return $this; }
$next 即参数为ServerRequestInterface $req, ResponseInterface $res的闭包,而$callable即我们的中间件。
中间件都添加到堆栈$this->stack[]上了,$next则是栈顶,而$this->seedMiddlewareStack();则把路由中间件第一个压栈了。
这就是官网调用顺序的流程了。
然而Hello 为何最后输出则还是费解,于是继续调试。
在vendor\slim\slim\Slim\Route.php里发现了痕迹:
__invoke函数中
if ($this->outputBuffering === false) {$newResponse = $handler($this->callable, $request, $response, $this->arguments);} else {try {ob_start();$newResponse = $handler($this->callable, $request, $response, $this->arguments);$output = ob_get_clean();} catch (Exception $e) {ob_end_clean();throw $e;}}
关键是$output = ob_get_clean();
我们的echo输出被路由中间件拦截了,并放入了$response->getBody()->write($output);
if (!empty($output) && $response->getBody()->isWritable()) {if ($this->outputBuffering === 'prepend') {// prepend output buffer content$body = new Http\Body(fopen('php://temp', 'r+'));$body->write($output . $response->getBody());$response = $response->withBody($body);} elseif ($this->outputBuffering === 'append') {// append output buffer content$response->getBody()->write($output);}}
在$response返回时才会输出,所以上面的Hello 是最后输出的。
那为啥$mw1、$mw2没有这个问题呢,因为我们的中间件就是直接输出,并不像路由中间件这么处理。
转载于:https://www.cnblogs.com/xdao/p/slim_middleware_thinking.html
slimphp中间件调用流程的理解相关推荐
- linux 驱动probe 被调用流程分析 理解1
原文链接:https://blog.csdn.net/goodnight1994/article/details/82082089 修改个别错误呈现 前言: 对于linux platform devi ...
- Android深入源代码分析理解Aidl总体调用流程(雷惊风)
2017年開始上班的第一天.老不想工作了,假期感觉还没開始就已经结束了,唉,时间就是这样,新的一年開始了,尽管非常不想干正事,没办法,必须干起来.由于后边的路还非常长,距离六十岁还非常远. 刚上班也没 ...
- 理解Dubbo的调用流程与Dubbo多协议解析
Dubbo作为目前国内主流的微服务框架之一 一.Dubbo的调用流程分析 Dubbo本身主要支持两种调用流程,包括直连提供者和基于注册中心的调用 直连提供者一般都是在开发和测试环境下使用 我们将所有的 ...
- RPC 笔记(01)— RPC概念、调用流程、RPC 与 Restful API 区别
1. 基本概念 PRC 远程过程调用 Remote Procedure Call,其就是一个节点请求另外一个节点提供的服务.当两个物理分离的子系统需要建立逻辑上的关联时,RPC 是牵线搭桥的常见技术手 ...
- SDIO_WiFi驱动学习之安卓WLAN架构介绍及调用流程分析
一.引言 上一篇博客介绍了MMC子系统和SDIO相关知识及架构,这一篇博客则分析一下安卓的WLAN架构及上层如何调用WLAN驱动的流程. 虽然我工作的开发环境是安卓系统,但由于我不是专业的安卓应用/框 ...
- RTSP播放器高RTSP兼容推流网页无插件流媒体播放器EasyPlayer-RTSP关于MP4的封装调用流程介绍
EasyPlayer-RTSP播放器是一套RTSP专用的播放器,包括有:Windows(支持IE插件,npapi插件).Android.iOS三个平台,是区别于市面上大部分的通用播放器,EasyPla ...
- Linux ALSA声卡驱动之七:录音(Capture) 调用流程
ALSA声卡驱动: 1.Linux ALSA声卡驱动之一:ALSA架构简介和ASOC架构简介 2.Linux ALSA声卡驱动之二:Platform 3. Linux ALSA声卡驱动之三:Platf ...
- android从应用到驱动之—camera(1)---程序调用流程
一.开篇 写博客还得写开篇介绍,可惜,这个不是我所擅长的.就按我自己的想法写吧. 话说camera模块,从上层到底层一共包含着这么几个部分: 1.apk------java语言 2.camera的ja ...
- 对ajax中onreadystatechange事件执行流程的理解
对Ajax中onreadystatechange事件执行流程的理解 onreadystatechange 事件 当请求被发送到服务器时,我们需要执行一些基于响应的任务. 每当 readyState 改 ...
最新文章
- Linux网络编程--TCP中的三次握手和四次挥手
- PHP开发之环境配置
- Android NDK-helloJNI
- zemax评价函数编辑器_ZEMAX与光学设计案例:激光扩束系统详细设计与公差分析(二)...
- java用中根后根序列构造二叉树,106. 从中序与后序遍历序列构造二叉树
- c++创建二叉树_数据结构:查找(4)|| 平衡二叉树
- 华为应用锁退出立即锁_华为P40系列三大安全锁,教你锁住你的隐私 - 企业资讯...
- python中的优化器有哪些_Python SciPy 优化器(Optimizers)
- android裁剪部分放大动画,【Android】图片放大被截了一部分之认识clipChildren属性的用法...
- 数学建模——什么是数学建模
- 遥感图像预处理—步骤
- 怎么看电脑的hdmi是输出还是输入_笔记本hdmi接口是输入还是输出
- shell中各种括号的作用详解()、(())、[]、[[]]、{}(推荐)
- 世界三大顶级音响_世界音响三个顶尖品牌 世界顶级音响哪个品牌好
- 删除一个字符串中指定位置上的字符
- 北航 计算机学院 加试两门,北航强军计划考研计算机学院招生.pdf
- winform 异步加载控件屏幕一闪一闪亮晶晶解决
- 教你破解隔壁妹子wifi密码,成功率高达90%
- 桂电的计算机专业研究生录取比例,桂电研究生就业待遇 桂林电子科技大学就业率...
- 网卡反复重启[why!why!why]