Codeigniter 4.0-dev 版源碼學習筆記之四——詳細路由過程

前言

我我的以爲在當前 MVC 流行的架構下,要想去了解一個框架,或者是一個基於此架構下的應用程序,最好的入手方式就是先看路由,雖然路由不是 MVC 裏的任何一個,可是知道了路由的前因後果就知道了整個框架或者是應用的結構。從一個請求開始,具體分配到哪一個 C 去執行的, C 裏又調用了哪些東西,整個脈絡也就清晰了。php

然而整個路由的實現的邏輯自己又是比較好理解的,無非就是從請求的 URL 中按着約定的規則取出 C 對應的 class 以及 method 便可。如此,咱們接下來詳細看看 CI 4 dev 版的路由具體實現的邏輯。segmentfault

找到路由邏輯的具體位置

上一節咱們說 Codeigniter.php 的時候講到, index.php 入口文件經過 $app->run() 調取了 Codeigniter 類中的 run 方法。 run 中又執行了 handleRequest 方法用來處理請求的具體信息。接着 handleRequest 調取 tryToRouteIt 來嘗試解析路由,此時代碼邏輯還在 Codeigniter.php 裏,真正的解析過程尚未開始。在 tryToRouteIt 方法中,經過 service 方式加載了 router 類,經過 system/config/service 加載 router 代碼以下,這也是一個服務加載的統一形式,其它的核心輔助類都是如此加載:數組

public static function router(\CodeIgniter\Router\RouteCollectionInterface $routes = null, $getShared = true)
{
    if ($getShared)
    {
        return self::getSharedInstance('router', $routes);
    }

    if (empty($routes))
    {
        $routes = self::routes(true);
    }

    return new \CodeIgniter\Router\Router($routes);
}

從 倒數第二行能夠看出加載的 router 類位於 system/router 下的 Router 類裏。架構

system/router/Router.php 解析路由的詳細過程

首先咱們把 Codeigniter.php 中調用該類的詳細代碼列出來以下:app

$this->controller = $this->router->handle($path);
$this->method     = $this->router->methodName();

關鍵的只有兩行,一行找類一行找方法。找類的那一行處理了大部分的邏輯,找方法的那一行就是簡單的 get 。框架

handle 方法源碼截圖

  1. 146-150 行,判斷 $uri 若是爲空,那麼返回默認路由。由於在該類的構造方法裏讀取了配置中的默認路由,所以此處直接返回配置便可。codeigniter

  2. 153-156 行,檢查路由配置文件裏的配置是否有和當前匹配的 URL ,有的話,直接返回配置的控制器便可。this

  3. 161-164 行,檢查是否開啓了自動路由匹配,若是沒有開啓,那麼讀取完配置好的路由都沒有結果,那麼就能夠 throw pageNoteFoundException 了。spa

  4. 166 行,真正的處理 CI 路由邏輯的地方。詳細見 autoRoute 方法。code

  5. 168 行,把處理完畢後找到的 controller 返回。

此方法經過調用其它方法已經實現了尋找 controller 的過程,主流程到此已經結束。

autoRoute 方法

該方法是自動按着約定規則去 controller 目錄去找路由的過程。

autoRoute 方法源碼截圖

  1. 442 行:將 URI 按着 / 打散成數組。

  2. 444 行:肯定 URI 裏是否包含 Controller 的目錄部分。該方法將 $segments 數組由 0 元素一次一次循環並匹配 application/controller 下的目錄,找到後而且該目錄下沒有同名的 PHP 文件即認爲是路徑組成部分,同時將該元素從 $segments 中去除,以保證 $segments 中剩下的僅僅是 class 與 method 內容。

  3. 448-456 行:去除路徑後發現 $segments 數組沒元素啦,那麼只能是默認處理了。不然直接彈出數組中的第一個元素便是 class 信息。

  4. 461-464 行:若是此時 $segments 中不爲空,那麼彈出數組中第一個元素是 method 信息。

  5. 466-469 行:若是此時 $segments 中還不爲空,那麼剩下的就是傳遞的參數信息。

  6. 472-476 行:判斷表明 controller 的文件存在的話 include 進來。

小結

至此,路由部分處理完了,找到的 controller 與 method 信息分別放到了對象對應的屬性裏。所以在 codeigniter.php 中用如下兩行就拿到了相應的信息:

$this->controller = $this->router->handle($path);
$this->method     = $this->router->methodName();

下一章應該會看看 CI 4 相對 CI 3 的變化。

此文能夠轉載,但轉載前須要發郵件到imustgxd*sina.cn進行溝通,未溝通的均視做侵權。 轉載同時需註明原文連接
(https://segmentfault.com/a/11...,並保留此段文字。

相關文章
相關標籤/搜索