定义中间件的步骤
默认中间件存放位置
'default_namespace' => 'app\\http\\middleware\\',
创建一个 Check中间件
param('name') == 'think') {
return redirect('index/think');
}
return $next($request);
}
}
中间件的入口执行方法必须是handle方法,而且第一个参数是Request对象,第二个参数是一个闭包。
如何理解$next($request)
1. new App())->run() 中 执行到了中间件调度方法
$response = $this->middleware->dispatch($this->request);
2.在 think\Middleware.php 中可以看到dispatch 方法 调用了
call_user_func($this->resolve($type), $request);
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
3. resolve() 是一个回调函数 其中执行了$middleware = array_shift($this->queue[$type]);删除并得到队列中的第一个元素 。下一步list($call, $param) = $middleware;
下面值关键的一步
$response = call_user_func_array(array('app\http\middleware\Check','handle'), [$request, $this->resolve(), $param]);
call_user_func_array ( callable $callback , array $param_arr )
把第一个参数作为回调函数(callback)调用,把参数数组作(param_arr)为回调函数的的参数传入。
这里的$this->resolve() 对应的就是 handle($request, \Closure $next) 的 \Closure $next 这个参数。
tp5.2中resolve() 方法如下
protected function resolve(string $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(), $param]);
} catch (HttpResponseException $exception) {
$response = $exception->getResponse();
}
if (!$response instanceof Response) {
throw new LogicException('The middleware must return Response instance');
}
return $response;
};
}