首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 實作 RESTful 路由分發器:從核心原理到完整類別設計

     編輯:PHP 相關知識

在現代 PHP 應用開發中,乾淨的 URL 結構與請求分發機制是基石。本文將帶你從零構建一個輕量級的 RESTful 路由類,涵蓋路由表定義、HTTP 方法匹配、動態參數提取、控制器自動載入與反射調用等核心功能。

核心設計思路

  • 路由表:以陣列定義路由規則,包含名稱、模式(HTTP 方法 + URI 模板)、對應的控制器動作。
  • 請求解析:從 $_SERVER 獲取當前請求的 URI 與 HTTP 方法。
  • 模式匹配:將 URI 模板轉換為正則表達式,支援 :param 風格的動態參數。
  • 分發執行:匹配成功後,透過反射機制實例化控制器並調用指定方法,注入提取的參數。

完整路由類實作

<?php
class Router {
    /** @var array 路由表 */
    private $routers = [
        ['name' => 'userlist', 'pattern' => 'get /user',       'action' => 'User#get'],
        ['name' => 'userinfo', 'pattern' => 'get /user/:id',   'action' => 'User#getById'],
        ['name' => 'useradd',  'pattern' => 'post /user',      'action' => 'User#add'],
        ['name' => 'userupdate','pattern' => 'put /user/:id',  'action' => 'User#update'],
        ['name' => 'userdel',  'pattern' => 'delete /user/:id','action' => 'User#delete'],
    ];

    /** 入口:分發當前請求 */
    public function dispatch() {
        $url    = $_SERVER['REQUEST_URI'];
        $method = $_SERVER['REQUEST_METHOD'];

        foreach ($this->routers as $router) {
            [$patternMethod, $patternUri] = explode(' ', $router['pattern'], 2);
            if (strcasecmp($patternMethod, $method) !== 0) continue;

            $params = $this->checkUrl($method, strtolower($url), strtolower($patternUri));
            if ($params !== null) {
                array_shift($params); // 移除正則匹配的完整字串
                return $this->invoke($router['action'], $params);
            }
        }
        // 無匹配路由
        http_response_code(404);
        echo '404 Not Found';
    }

    /** 透過反射調用控制器動作 */
    private function invoke(string $action, array $params) {
        [$className, $methodName] = explode('#', $action);
        $className .= 'Action'; // 慣例:控制器類名以 Action 結尾

        $file = __DIR__ . DIRECTORY_SEPARATOR . 'action' . DIRECTORY_SEPARATOR . $className . '.php';
        if (!file_exists($file)) {
            http_response_code(404);
            echo "404: Controller $className not found";
            return;
        }
        require $file;

        $refClass = new ReflectionClass($className);
        if (!$refClass->hasMethod($methodName)) {
            http_response_code(404);
            echo "404: Method $methodName not found in $className";
            return;
        }

        $instance = $refClass->newInstance();
        $refMethod = $refClass->getMethod($methodName);
        $refMethod->invokeArgs($instance, $params);
    }

    /** 正則匹配 URI 並提取參數 */
    private function checkUrl(string $method, string $url, string $pattern): ?array {
        // 將 /user/:id 轉換為正則:/user/([^/]+)
        $pattern = '/' . str_replace('/:', '/([^/]+)', trim($pattern, '/')) . '/?$';
        if (preg_match($pattern, $url, $matches)) {
            return $matches;
        }
        return null;
    }
}

// 使用範例
$router = new Router();
$router->dispatch();
?>

關鍵細節解析

1. 動態參數支援

路由模式中的 :id 會被轉換為正則捕獲組 ([^/]+),匹配非斜線字符,提取出的值將按順序傳遞給控制器方法。

2. 反射機制解耦

使用 ReflectionClass 動態實例化控制器並調用方法,避免硬編碼依賴,符合依賴倒置原則。

3. 錯誤處理

提供清晰的 404 回應:路由不存在、控制器檔案缺失、方法未定義等情況皆有對應處理。

擴展建議

  • 中介軟體支援:在 dispatch() 前後掛載前置/後置處理器(如認證、日誌、CORS)。
  • 路由分組與前綴:支援 /api/v1 等前綴分組,簡化大型應用路由管理。
  • 命名路由與 URL 生成:增加 url('userinfo', ['id' => 123]) 輔助函數生成反向連結。
  • 快取優化:將編譯後的正則模式快取,避免每次請求重複解析。

這個路由器雖然精簡,但已具備現代 PHP 框架路由系統的核心骨架。理解其運作原理,有助於你在使用 Laravel、Slim 或 Symfony 等框架時,更深入地掌握其底層機制,也能在輕量專案中直接落地使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved