<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智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                1. 入口文件先實例化容器,然后再通過容器去獲取到Http對象 (Web管理類),然后執行Http對象中的run方法。 2. 方法內會創建一個Request對象,然后將對象綁定到容器內。然后再到runWithRequest方法,執行應用程序 3. runWithRequest方法內會初始化當前應用,簡單來說就比如加載一下語言包,加載一下應用文件。common.php公共函數文件。helper.php助手函數文件、.env環境變量、運行開始的時間、設置時區、加載中間件等等。然后到dispatchToRoute方法,傳入當前的Request請求對象。 4. dispatchToRoute方法,這里我姑且稱為路由初始化方法。這里主要就是檢測配置文件,是否開啟了路由。如果開啟了路由。就加載路由文件。并且設置一個匿名函數。只有在調用的時候才會加載設置的路由。接著會通過容器獲取route類的實例。并且傳入當前Request對象和路由配置的匿名函數并執行里面的dispatch方法 5. dispatch方法,主要就是路由初始化。判斷路由是否配置。如果沒有配置就直接執行默認控制器和默認方法。如果有的話。就加載一下路由配置,再執行check方法,通過check方法。去檢測是什么路由。然后調用url方法傳入當前的url地址 6. url方法執行并且會返回一個Url基礎類 7. 這里我稱之為url且切割類吧。他主要的作用就是將傳入的Request對象,rule路由規則對象,以及當前的url地址。把url地址解析。這里又去調用了一個parseUrl方法。 8. 這個方法我就不多介紹了。它主要的作用就是分割出來要執行的control和function。 9. 到這里就結束了url的部分。又回到了第五部。去調用url類中的init方法(路由后置操作。中間件).然后通過middleware中的then。到最后執行一個上一步返回的Url類中的run方法 10. run這里主要就是最通過exec再去獲取控制器(controller)和對應的方法(function)的結果。然后創建一個Response對象。最后返回 11. 最后回到了入口文件run方法下面還有一個send方法。源碼就不貼了。他的作用就是輸出 12. 入口文件最后一行。調用了一下Http類的end方法。簡單說就是掛個HttpEnd中間件。然后執行中間件。最后再記錄一下日志。 ## 0x01 源碼解析 ### 1、public/index.php ~~~ // [ 應用入口文件 ] //定義根命名空間 namespace think; //引入composer require __DIR__ . '/../vendor/autoload.php'; //通過Ioc容器將HTTP類實例出來 // 執行HTTP應用并響應 $http = (new App())->http; //執行HTTP類中的run類方法 并返回一個response對象 $response = $http->run(); //執行response對象中的send類方法 該方法是處理并輸出http狀態碼以及頁面內容 $response->send(); //執行response對象中的send方法 $http->end($response); ~~~ ### 2、通過\\Think\\App容器獲取到Http對象,然后再執行Http對象中的run方法 ~~~ /** * 執行應用程序 * @access public * @param Request|null $request * @return Response */ public function run(Request $request = null): Response { //判斷是否傳入Request對象,如果沒有則創建 $request = $request ?? $this->app->make('request', [], true); //將Request綁定到App容器內 $this->app->instance('request', $request); try { //runWithRequest方法 作用是執行應用程序 $response = $this->runWithRequest($request); } catch (Throwable $e) { //如果捕捉到Throwable異常 則執行reportException方法 //調用Handle::class實例中的report方法。收集異常信息 $this->reportException($e); //通過調用Handle::class實例中的render方法 //獲取異常信息輸出流 $response = $this->renderException($request, $e); } //return 內容 return $response; } ~~~ ### 3、\\Think\\Http->runWithRequest() 初始化應用程序,并執行 ~~~ protected function runWithRequest(Request $request) { //初始化應用程序 $this->initialize(); // 加載全局中間件 $this->loadMiddleware(); // 設置開啟事件機制 $this->app->event->withEvent($this->app->config->get('app.with_event', true)); // 監聽HttpRun $this->app->event->trigger(HttpRun::class); //這里重點 return $this->app->middleware->pipeline() ->send($request) ->then(function ($request) { //通過dispatchToRoute方法加載路由 return $this->dispatchToRoute($request); }); } ~~~ ### 4、\\Think\\Http->dispatchToRoute()?? ~~~ protected function dispatchToRoute($request) { //通過容器控制反轉快速獲取config類實例 //并獲取配置文件中的with_route 判斷是否加載路由 //如果加載則返回一個匿名函數。里面是路由文件內的設置 $withRoute = $this->app->config->get('app.with_route', true) ? function () { $this->loadRoutes(); } : null; //執行\Think\Route類中的dispatch方法,并且將獲取到的路由 //文件以及當前的Request實例傳入到路由中,然后進行路由調度 return $this->app->route->dispatch($request, $withRoute); } ~~~ ### 5、\\Think\\Route->dispatch()? 路由 ~~~ public function dispatch(Request $request, $withRoute = null) { //設置傳入的Request對象到當前對象的屬性上 $this->request = $request; //同上 這個是設置host $this->host = $this->request->host(true); //執行Route init 方法 初始化 $this->init(); //判斷的withRoute是否為真 if ($withRoute) { //執行傳入過來的匿名函數,加載路由 $withRoute(); //官方注釋的是檢測url路由,我這里姑且認為是路由分發吧 //check返回的是think\route\Dispatch 路由調度基礎類對象 $dispatch = $this->check(); } else { //調用think\route\dispatch\Url類 //將當前的url地址傳入進去,進行默認的url解析 $dispatch = $this->url($this->path()); } //執行Dispatch對象中的init方法 //這里用于綁定控制器和方法以及路由后置操作,例如:中間件、綁定模型數據 $dispatch->init($this->app); //執行路由調度。并返回一個Response對象 return $this->app->middleware->pipeline('route') ->send($request) ->then(function () use ($dispatch) { return $dispatch->run(); }); } ~~~ ### 6、\\Think\\Route->init()? 初始化 ~~~ protected function init() { //合并默認配置以及讀取到的route.php配置 $this->config = array_merge($this->config, $this->app->config->get('route')); //判斷路由中間件是否存儲,如果存在則調用middleware類中的import方法 //注冊route中間件 if (!empty($this->config['middleware'])) { $this->app->middleware->import($this->config['middleware'], 'route'); } //是否延遲解析 $this->lazy($this->config['url_lazy_route']); //讀取到的 是否合并路由配置項賦值到類變量mergeRuleRegex中 $this->mergeRuleRegex = $this->config['route_rule_merge']; //獲取配置:是否刪除url最后的斜線 $this->removeSlash = $this->config['remove_slash']; //是否去除url最后的斜線 $this->group->removeSlash($this->removeSlash); } ~~~ ### 7、Think\\Route\\Dispatch->init() ``` `public``function``init(App``$app``)` `{` `$this``->app =``$app``;` `// 執行路由后置操作` `$this``->doRouteAfter();` `}` ``` ### 8、Think\\Route\\Dispatch->run() ``` `public``function``run(): Response` `{` `//判斷$this->rule路由規則是否為RuleItem類的實例` `//判斷當前請求方法,是不是OPTIONS以及` `//判斷當前路由規則是否為自動注冊的OPTIONS路由` `if``(``$this``->rule``instanceof``RuleItem &&``$this``->request->method() ==``'OPTIONS'``&&``$this``->rule->isAutoOptions()) {` `//獲取當前的路由列表` `$rules``=``$this``->rule->getRouter()->getRule(``$this``->rule->getRule());` `$allow``= [];` `foreach``(``$rules``as``$item``) {` `//這里是循環把所有路由全部轉成大寫` `$allow``[] =``strtoupper``(``$item``->getMethod());` `}` `//創建并返回一個Response對象,調用create靜態方法` `return``Response::create(``''``,``'html'``, 204)->header([``'Allow'``=> implode(``', '``,``$allow``)]);` `}` `//如果上面的不匹配則調用當前Dispatch類中的exec方法` `//實例化控制器以及方法` `$data``=``$this``->``exec``();` `//最后動態的返回一個Response對象。xml、json等等` `return``$this``->autoResponse(``$data``);` `}` ``` ### 9、\\Think\\Route->check()? ``` `public``function``check(): Dispatch` `{` `//轉換PATH_INFO分隔符,拼接url` `$url``=``str_replace``(``$this``->config[``'pathinfo_depr'``],``'|'``,``$this``->path());` `//獲取是否完全匹配 配置項` `$completeMatch``=``$this``->config[``'route_complete_match'``];` `//調用checkDomain檢測是否為域名路由如果不是則返回false` `//如果是域名路由,則返回一個Domain對象。并且執行對象中的check方法` `//并把當前的Request請求對象以及url地址和是否完全匹配路由項傳入進去` `$result``=``$this``->checkDomain()->check(``$this``->request,``$url``,``$completeMatch``);` `//判斷result是否為false 也就是不是域名路由` `//再判斷是否為跨域路由` `if``(false ===``$result``&& !``empty``(``$this``->cross)) {` `// 如果是跨域路由,就將當前的Request請求對象以及url地址和是否完全匹配路由項傳入進去` `$result``=``$this``->cross->check(``$this``->request,``$url``,``$completeMatch``);` `}` `//如果是域名路由` `if``(false !==``$result``) {` `//直接返回 $result變量 變量內存儲著 RuleGroup對象實例` `//路由規則` `return``$result``;` `}``elseif``(``$this``->config[``'url_route_must'``]) {` `//判斷是否啟用了強制路由,如果啟用了強制路由` `//然后域名路由也匹配不上。就觸發一個路由` `//找不到的異常類` `throw``new``RouteNotFoundException();` `}` `//以上都不匹配,則調用url函數,傳入當前的url地址` `//返回一個Url類實例` `return``$this``->url(``$url``);` `}` ``` ### 10、\\Think\\Route->url() ``` `public``function``url(string``$url``): UrlDispatch` `{` `return``new``UrlDispatch(``$this``->request,``$this``->group,``$url``);` `}` ``` ### 11、\\Think\\Route\\dispatch\\Url? url切割類(自己給的稱呼) ``` `//構造函數` `public``function``__construct(Request``$request``, Rule``$rule``,``$dispatch``,``array``$param``= [], int``$code``= null)` `{` `//獲取傳入來的Request對象,存儲到類成員變量內` `$this``->request =``$request``;` `//獲取到路由列表,也放到類成員變量內` `$this``->rule??? =``$rule``;` `// 調用類中的parseUrl方法 解析URL規則` `$dispatch``=``$this``->parseUrl(``$dispatch``);` `//調用父類構造函數` `parent::__construct(``$request``,``$rule``,``$dispatch``,``$this``->param,``$code``);` `}` `protected``function``parseUrl(string``$url``):``array` `{` `//獲取到分隔符` `$depr``=``$this``->rule->config(``'pathinfo_depr'``);` `//獲取當前域名` `$bind``=``$this``->rule->getRouter()->getDomainBind();` `//如果域名不為空,并且正則匹配的到` `if``(``$bind``&& preg_match(``'/^[a-z]/is'``,``$bind``)) {` `//切割url,換成配置項中的PATH_INFO分隔符` `$bind``=``str_replace``(``'/'``,``$depr``,``$bind``);` `// 如果有域名綁定` `$url``=``$bind``. (``'.'``!=``substr``(``$bind``, -1) ?``$depr``:``''``) . ltrim(``$url``,``$depr``);` `}` `//調用rule類中的parseUrlPath方法,切割pathinfo參數` `//如果url中有參數 返回一個demo吧? ['Index','Demo']` `//第一個為控制器、第二個為方法` `$path``=``$this``->rule->parseUrlPath(``$url``);` `//如果切割的pathinfo為空,則直接返回一個[null,null] 這樣的一個空數組` `if``(``empty``(``$path``)) {` `return``[null, null];` `}` `//獲取到第一個下標? 控制器` `$controller``= !``empty``(``$path``) ?``array_shift``(``$path``) : null;` `//正則匹配,如果匹配不到。就彈出一個HttpException異常` `if``(``$controller``&& !preg_match(``'/^[A-Za-z0-9][\w|\.]*$/'``,``$controller``)) {` `throw``new``HttpException(404,``'controller not exists:'``.``$controller``);` `}` `//獲取到第二個下標? 方法 function` `// 解析操作` `$action``= !``empty``(``$path``) ?``array_shift``(``$path``) : null;` `$var`???`= [];` `// 解析額外參數` `//類似于? /index.php/Index/Users/Pascc` `//這樣就會返回一個 三個下標的數組` `if``(``$path``) {` `//這里將多余的下標,放到var變量內` `preg_replace_callback(``'/(\w+)\|([^\|]+)/'``,``function``(``$match``)``use``(&``$var``) {` `$var``[``$match``[1]] =``strip_tags``(``$match``[2]);` `}, implode(``'|'``,``$path``));` `}` `//獲取到泛域名 再判斷其中是否有*符號` `$panDomain``=``$this``->request->panDomain();` `if``(``$panDomain``&&``$key``=``array_search``(``'*'``,``$var``)) {` `// 泛域名賦值` `$var``[``$key``] =``$panDomain``;` `}` `// 設置當前請求的參數` `$this``->param =``$var``;` `// 封裝路由` `$route``= [``$controller``,``$action``];` `//判斷路由,是否存在 不存在則彈出未找到路由` `if``(``$this``->hasDefinedRoute(``$route``)) {` `throw``new``HttpException(404,``'invalid request:'``.``str_replace``(``'|'``,``$depr``,``$url``));` `}` `//返回路由` `return``$route``;` ``` ### 12、\\Think\\Route\\dispatch\\controller->init()? 綁定控制器和方法 ~~~ public function init(App $app) { parent::init($app); $result = $this->dispatch; if (is_string($result)) { $result = explode('/', $result); } // 獲取控制器名 $controller = strip_tags($result[0] ?: $this->rule->config('default_controller')); if (strpos($controller, '.')) { $pos = strrpos($controller, '.'); $this->controller = substr($controller, 0, $pos) . '.' . Str::studly(substr($controller, $pos + 1)); } else { $this->controller = Str::studly($controller); } // 獲取操作名 $this->actionName = strip_tags($result[1] ?: $this->rule->config('default_action')); // 設置當前請求的控制器、操作 $this->request ->setController($this->controller) ->setAction($this->actionName); } ~~~ ### 13、接下來流程就是回到第5步 #### 最終會返回一個Response對象。流程又回到了第2步過程 ### 14、然后會在入口文件中 ``` `namespace``think;` `//引入composer` `require``__DIR__ .``'/../vendor/autoload.php'``;` `$http``= (``new``App())->http;` `$response``=``$http``->run();` `//執行返回的Response對象中的send方法` `//執行response對象中的send類方法? 該方法是處理并輸出http狀態碼以及頁面內容` `$response``->send();` `//執行Http對象中的send方法` `$http``->``end``(``$response``);` `//最終輸出到頁面上我` ```
                  <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>

                              哎呀哎呀视频在线观看