1. 程式人生 > >Tp5.2 定義中介軟體時的Closure $next怎麼理解

Tp5.2 定義中介軟體時的Closure $next怎麼理解

定義中介軟體的步驟

預設中介軟體存放位置 

'default_namespace' => 'app\\http\\middleware\\',

建立一個 Check中介軟體 

<?php

namespace app\http\middleware;

class Check
{
    public function handle($request, \Closure $next)
    {
        if ($request->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;
        };
}