| 方式 | 原理 | 優缺點 |
| 隱藏副檔名 | URL 重寫隱藏 .php | 簡單但偽靜態、SEO 效果有限、不推薦 |
| URL 重寫 | Apache mod_rewrite / Nginx rewrite 實現虛擬路徑 | 標準做法、靈活強大、推薦生產環境使用 |
| 強制檔案解析 | Apache ForceType 將無副檔名檔案解析為 PHP | 無需 rewrite 模組、但靈活度較低、較少見 |
本文採用方式二(URL 重寫)與方式三(ForceType)結合的方案,實現乾淨的虛擬路徑。
目錄結構規劃
webroot/
├── .htaccess # Apache 重寫規則
├── index.php # 統一入口檔案
├── Application.php # 應用核心類
├── Controller/ # 控制器目錄
│ ├── GoodController.php
│ └── BadController.php
├── Model/ # 模型目錄
└── View/ # 視圖目錄
核心檔案實作
1. .htaccess - 重寫規則
<Files index>
ForceType application/x-httpd-php
</Files>
# 或者使用 mod_rewrite(推薦)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
</IfModule>
注意: Windows 下無法直接建立 .htaccess,需在命令列執行 copy nul .htaccess 或使用編輯器另存為。
2. index.php - 統一入口
<?php
/**
* 統一入口檔案
* 職責:初始化環境、載入核心、啟動路由分發
*/
require_once "Application.php";
// 初始化應用
$app = new Application();
// 解析請求路徑
$app->parse();
// 執行分發
$app->go();
?>
3. Application.php - 應用核心類
<?php
class Application {
private $controller = 'Index'; // 預設控制器
private $action = 'index'; // 預設動作
private $params = []; // 路由參數
/**
* 解析請求路徑
* 例:/test/Good/param1/value1 → Controller=Good, Action=test
*/
public function parse() {
// 獲取 PATH_INFO
$pathInfo = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : '';
// 移除首尾斜線,分割段落
$segments = array_filter(explode('/', trim($pathInfo, '/')));
if (empty($segments)) return; // 使用預設值
// 第一段作為控制器名(首字母大寫 + Controller)
$this->controller = ucfirst(array_shift($segments)) . 'Controller';
// 第二段作為動作名
if (!empty($segments)) {
$this->action = array_shift($segments);
}
// 剩餘段落作為參數鍵值對
$this->params = $segments;
}
/**
* 執行控制器動作
*/
public function go() {
$controllerFile = "Controller/{$this->controller}.php";
// 檢查控制器檔案是否存在
if (!file_exists($controllerFile)) {
$this->show404("控制器 {$this->controller} 不存在");
return;
}
require_once $controllerFile;
if (!class_exists($this->controller)) {
$this->show404("類別 {$this->controller} 未定義");
return;
}
$controller = new $this->controller();
// 檢查動作方法是否存在
if (!method_exists($controller, $this->action)) {
$this->show404("動作 {$this->action} 不存在");
return;
}
// 準備參數:將鍵值對轉為關聯陣列
$args = [];
for ($i = 0; $i < count($this->params); $i += 2) {
$key = $this->params[$i];
$value = isset($this->params[$i + 1]) ? $this->params[$i + 1] : null;
$args[$key] = $value;
}
// 呼叫控制器動作
call_user_func_array([$controller, $this->action], $args);
}
private function show404($message) {
header("HTTP/1.0 404 Not Found");
echo "404 Not Found
{$message}
";
exit;
}
}
4. 控制器範例
<?php
// Controller/GoodController.php
class GoodController {
public function test($id = null, $type = 'default') {
echo "GoodController::test()
";
echo "ID: {$id}
";
echo "Type: {$type}
";
// 實際開發中這裡會調用 Model 並載入 View
}
public function list() {
echo "GoodController::list()
";
// 列表邏輯
}
}
// Controller/BadController.php
class BadController {
public function test() {
echo "BadController::test()
";
}
}
URL 映射範例
| 訪問 URL | 控制器 | 動作 | 參數 |
| / | IndexController | index | - |
| /Good/test | GoodController | test | - |
| /Good/test/id/123/type/json | GoodController | test | id=123, type=json |
| /Bad/test | BadController | test | - |
進階擴展建議
1. 支援模組/分組
// 解析邏輯擴展:/admin/user/list → Module=Admin, Controller=UserController, Action=list
if ($segments[0] === 'admin') {
array_shift($segments);
$this->module = 'Admin';
// 命名空間:Admin\Controller\UserController
}
2. RESTful 風格路由
// 根據 HTTP 方法自動映射動作
$method = $_SERVER['REQUEST_METHOD'];
$actionMap = [
'GET' => 'index', // 列表/詳情
'POST' => 'create', // 新增
'PUT' => 'update', // 更新
'DELETE' => 'delete', // 刪除
];
$this->action = $actionMap[$method] ?? $this->action;
3. 路由表配置
// 替代自動解析,使用顯式路由表
$routes = [
'user/login' => ['UserController', 'login'],
'user/register' => ['UserController', 'register'],
'product/:id' => ['ProductController', 'detail'],
'api/:version/:resource' => ['ApiController', 'dispatch'],
];
// 匹配並提取參數
4. 安全性加固
- 控制器名稱白名單驗證,防止任意檔案包含
- 輸入參數過濾與驗證
- 關閉
display_errors,記錄錯誤日誌而非顯示
- 使用
.htaccess 禁止直接訪問 Controller/、Model/ 目錄
Nginx 環境配置
若使用 Nginx,需在虛擬主機配置中加入:
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
結語
統一入口是 MVC 架構的基石。通過 .htaccess(或 Nginx rewrite)實現虛擬路徑,配合 Application 核心類解析路由、分發控制器,即可建立清晰、安全、可擴展的 PHP 應用基礎。下一篇將深入探討 Model 層設計與資料庫抽象。
- 上一篇文章: VC++中動態鏈接庫(DLL)的五種鏈接方法詳解
- 下一篇文章: PHP.MVC 模板標籤系統深度解析
Copyright ©
程式碼之家 All Rights Reserved