欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程语言 > php >内容正文

php

slimphp中间件调用流程的理解

发布时间:2025/4/14 php 44 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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 

不难看出实际是 1、调用$mw2 输出 middleware 2 start   2、调用$mw2里的$next即$mw1 输出middleware 1 start  3、$mw1再调用$next,而此时没有中间件了,直接输出了middleware 1 end   4、由于$mw2还没return,还在调用栈里,接着输出middleware 2 end 5、对于这个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中间件调用流程的理解的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。