<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] ## 1 Middleware實現 ### 0 實現文件 ~~~ \library\think\Middleware.php ~~~ ### 1 添加middleware #### 1 add() ~~~ public function add($middleware) { if (is_null($middleware)) { return; } $middleware = $this->buildMiddleware($middleware); if ($middleware) { $this->queue[] = $middleware; } } ~~~ >[danger] add()方法將中間件$middleware添加到中間件隊列queue數組的末尾 > >其中的buildMiddleware()方法會根據傳入的$middleware不同形式進行不同處理。 >$middleware主要分為 閉包中間件 和 類中間件 > >buildMiddleware()在下面的輔助方法一節詳細分析 #### 2 unshift() ~~~ public function unshift($middleware) { if (is_null($middleware)) { return; } $middleware = $this->buildMiddleware($middleware); if ($middleware) { array_unshift($this->queue, $middleware); } } ~~~ >[danger] unshift()方法將$middleware中間件添加到中間隊列queue數組的開始部分 > >與add()方法一樣要經過buildMiddleware()方法處理 > >不同的是add()添加到中間件隊列末尾,unshift()添加到中間件隊列開始 > #### 3 import() ~~~ public function import(array $middlewares = []) { foreach ($middlewares as $middleware) { $this->add($middleware); } } ~~~ >[danger] import()添加多個中間件到中間件隊列queue的末尾 > ### 2 調用middleware #### 1 dispatch() ~~~ public function dispatch(Request $request) { return call_user_func($this->resolve(), $request); } ~~~ >[danger] disptach()依次調用中間件, >其中的resolve()方法實現中間件執行的具體過程 >resolve()在下面的輔助方法一節詳細分析 #### 2 all() ~~~ public function all() { return $this->queue; } ~~~ >[danger] all()獲取已注冊的中間件隊列 > ## 2 Middleware調用 >[danger] 中間件在框架整體執行流程的入口在App.php的run()方法中 ~~~ $this->middleware->add(function (Request $request, $next) use ($dispatch, $data) { if (is_null($data)) { try { // 執行調度 $data = $dispatch->run(); } catch (HttpResponseException $exception) { $data = $exception->getResponse(); } } // 輸出數據到客戶端 if ($data instanceof Response) { $response = $data; } elseif (!is_null($data)) { // 默認自動識別響應輸出類型 $isAjax = $request->isAjax(); $type = $isAjax ? $this->config('app.default_ajax_return') : $this->config('app.default_return_type'); $response = Response::create($data, $type); } else { $response = Response::create(); } return $response; }); $response = $this->middleware->dispatch($this->request); ~~~ >[danger] 在App.php的run()方法的最后 > 獲取app容器的middleware屬性,也就是全局的中間件對象。 > 調用middleware對象的add()方法 > 添加應用調度`$data = $dispatch->run();`到中間件隊列末尾 > 接著調用middleware對象的disptach()開始依次執行中間件 >[danger]在框架的初始化文件base.php(thinkphp\base.php)中注冊middleware類到容器中 ~~~ // 注冊核心類到容器 Container::getInstance()->bind([ 'app' => App::class, 'build' => Build::class, 'cache' => Cache::class, 'config' => Config::class, 'cookie' => Cookie::class, 'debug' => Debug::class, 'env' => Env::class, 'hook' => Hook::class, 'lang' => Lang::class, 'log' => Log::class, 'middleware' => Middleware::class, 'request' => Request::class, 'response' => Response::class, 'route' => Route::class, 'session' => Session::class, 'url' => Url::class, 'validate' => Validate::class, 'view' => View::class, 'rule_name' => route\RuleName::class, // 接口依賴注入 'think\LoggerInterface' => Log::class, ]); ~~~ >[danger]因此可以在App中通過$this->middleware獲取Middleware對象 ## 3 輔助方法 #### 1 buildMiddleware() ~~~ protected function buildMiddleware($middleware) { 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'); } if (false === strpos($middleware, '\\')) { $value = Container::get('config')->get('middleware.' . $middleware); $middleware = $value ?: Container::get('app')->getNamespace() . '\\http\\middleware\\' . $middleware; } if (is_array($middleware)) { return $this->import($middleware); } if (strpos($middleware, ':')) { list($middleware, $param) = explode(':', $middleware, 2); } return [[Container::get($middleware), 'handle'], isset($param) ? $param : null]; } ~~~ >[danger] buildMiddleware()方法主要根據middleware是閉包還是類進行不同的處理 > > >**1** 首先假設是單個中間件注冊,單個中間可以是帶參數的閉包和類。 > 首先檢查是否為數組,然后將其分為真正的中間件$midlleware和$param。 > 如果$middleware是閉包 那么直接返回`[$middleware,$param]`形式的數組,然后添加到中間件隊列中。 > > 如果不是閉包,則檢查是否為類名字符串, > 如果類名字符串中包含命名空間`\\`則 > 首先讀取配置文件middleware.php注冊的中間信息。 > 如果從配置文件中middleware.php中獲取失敗,則從應用目錄app\http\middleware中讀取對應的中間件類。 > > >**2** 然后假設傳入的數組中間件,則調用impore()進行批量注冊 。 > 如果傳入的是一個數組則調用import()方法注冊多個中間件。 > import()方法遍歷數組信息再次調用buldMiddleware()處理多個中間件。 > 類的中間件數組格式是`[[[Container::get($middleware), 'handle'], isset($param) ? $param : null];]`也就是以中間件類的handle()方法為調用方法,傳入參數$param, > > **3** 綜上buildeMiddleware()方法處理多個中間件和單個中間件的參數。其中單個中間件還分為閉包中間件和類中間件 > #### 2 resolve ~~~ protected function resolve() { return function (Request $request) { $middleware = array_shift($this->queue); 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; }; } ~~~ >[danger] reolve()方法則依次將注冊到中間件隊列的中間件組織為一個**洋蔥形式的遞歸調用閉包** > >首先array_shift()獲取中間件隊列的第一個中間件 >list()將注冊的中間件分為中間件調用和中間件參數 >然后call_user_func_array()調用中間件 >需要注意的是call_user_func_array()的參數, >第一個是中間件調用$call >第二個是$this->resolve()方法, >第三個參數才是真正傳入中間件的參數$param. >這里$this->resolve()將會再次獲取下個中間件的閉包形式, >下個中間件的閉包中將再次獲取下下個中間件的閉包形式。 >因此這里resolve()將中間件組織成為一個遞歸調用閉包。 > >**然后執行第一層的閉包,進入第二層閉包,然后再執行第三層閉包,直到最后一層,然后再往上依次返回第一層閉包。** > >這里是中間件執行順序的核心邏輯
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看