路由是 MVC 框架的「交通指揮官」,負責將 URL 映射到具體的控制器與動作。本文深入剖析單入口模式下路由的核心原理,並通過一個極簡卻完整的代碼示例,演示如何從 $_SERVER 變量提取路由信息、動態加載控制器、調用動作方法並傳遞參數。
典型單入口 URL 格式:
domain/index.php/ControllerName/ActionName/param1/param2
index.php:唯一入口文件ControllerName:控制器類名ActionName:動作方法名paramN:傳遞給動作的參數Web 服務器僅識別 index.php,後續路徑解析完全在 PHP 層完成。
| 變量 | 示例值 | 作用 |
|---|---|---|
SCRIPT_NAME | /MVC/index.php | 當前執行腳本路徑 |
REQUEST_URI | /MVC/index.php/class/function/var1 | 完整請求 URI(含查詢字符串) |
路由提取公式:REQUEST_URI - SCRIPT_NAME = 路由路徑
<?php
// 定義應用根路徑
define('APPPATH', trim(__DIR__, '/'));
// 獲取請求地址
$root = $_SERVER['SCRIPT_NAME'];
$request = $_SERVER['REQUEST_URI'];
// 提取 index.php 後面的路徑
$url = trim(str_replace($root, '', $request), '/');
$URI = array();
// 默認控制器與動作
if (empty($url)) {
$class = 'index';
$func = 'welcome';
} else {
$URI = explode('/', $url);
// 至少包含控制器名
$class = $URI[0];
// 若無動作名,默認 index
$func = isset($URI[1]) ? $URI[1] : 'index';
}
// 加載控制器文件
$controllerFile = APPPATH . '/application/controllers/' . $class . '.php';
if (file_exists($controllerFile)) {
include $controllerFile;
} else {
die('Controller not found: ' . $class);
}
// 實例化控制器(類名首字母大寫)
$obj = new ucfirst($class);
// 調用動作方法,傳遞剩餘參數
call_user_func_array(
array($obj, $func),
array_slice($URI, 2) // 從第3個元素開始作為參數
);
<?php
class Index {
public function welcome() {
echo 'I am default controller';
}
}
<?php
class Hello {
public function index() {
echo 'hello world';
}
public function name($name) {
echo 'hello ' . $name;
}
}
| 請求 URL | 匹配控制器 | 調用方法 | 參數 | 輸出結果 |
|---|---|---|---|---|
/index.php/hello/name/barbery | Hello | name | ['barbery'] | hello barbery |
/index.php/hello | Hello | index | [] | hello world |
/index.php/ | Index | welcome | [] | I am default controller |
/user/{id:\d+} 參數約束route('user.profile', ['id'=>1]) 生成 URL路由的本質是 字符串解析 + 文件加載 + 反射調用。掌握這一核心機制,能幫助您:
建議在理解本文極簡實現後,閱讀 FastRoute、League/Route 等專業路由庫源碼,領略生產級路由的設計藝術。