企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 中间件的载入 中间件主要用于拦截或过滤应用的http请求,并进行必要的业务处理。 默认的中间件类文件的命名空间是app\http\middleware。可以通过配置文件配置属性`default_namespace`,来设置。在app类中是通过应用的初始化,来加载中间件的配置文件。应用中间件的配置文件在应用目录下`middleware.php`。模块中间件的配置文件在模块目录下的`middleware.php` ; ``` if (is_file($path . 'middleware.php')) { $middleware = include $path . 'middleware.php'; if (is_array($middleware)) { $this->middleware->import($middleware); } } ``` middleware类是通过import方法导入中间件,import方法在通过循环调用add方法将中间件注册到middleware类的$queue的数组中。 ``` public function add($middleware, $type = 'route') { if (is_null($middleware)) { return; } // 调用buildMiddleware方法进行中间件的解析 $middleware = $this->buildMiddleware($middleware, $type); if ($middleware) { $this->queue[$type][] = $middleware; } } ``` 在buildMiddleware方法中,进行中间件的解析和拼装。 ``` protected function buildMiddleware($middleware, $type = 'route') { if (is_array($middleware)) { list($middleware, $param) = $middleware; } // 若是闭包中间件 则返回数组 [闭包函数,数组] if ($middleware instanceof \Closure) { return [$middleware, isset($param) ? $param : null]; } if (!is_string($middleware)) { throw new InvalidArgumentException('The middleware is invalid'); } // $middleware 中不包含 \\ 符号 if (false === strpos($middleware, '\\')) { if (isset($this->config[$middleware])) { $middleware = $this->config[$middleware]; } else { $middleware = $this->config['default_namespace'] . $middleware; } } if (is_array($middleware)) { return $this->import($middleware, $type); } if (strpos($middleware, ':')) { list($middleware, $param) = explode(':', $middleware, 2); } // 找到中间件所对应的类,并进行实例化。 // 最终返回 [[中间件实例, 'handle'], 参数]。 $middleware_item = [[$this->app->make($middleware), 'handle'], isset($param) ? $param : null]; return $middleware_item; } ``` ## 中间件的调度 在app类中,通过调用middleware类的dispatch方法,进行中间件的调度。dispatch方法通过使用php内置函数`call_user_func`调用resolve方法。 resolve方法返回一个匿名函数。匿名函数先取出$queue数组中第一个中间件,然后通过php内置函数call_user_func_array调用中间件中的handle方法。(handle函数的第二个参数也是传入resolve方法的匿名函数)。 ``` protected function resolve($type = 'route') { return function (Request $request) use ($type) { $middleware = array_shift($this->queue[$type]); if (null === $middleware) { throw new InvalidArgumentException('The queue was exhausted, with no response returned'); } 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 方法中,必须要返回一个response对象。 ``` public function handle($request, \Closure $next) { echo "action"; $response = $next($request); echo "end"; return $response; } ```