Tp5.2 定义中间件时的Closure $next怎么理解

定义中间件的步骤

默认中间件存放位置 

'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;
        };
}

 

你可能感兴趣的:(PHP)