首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

PHP實現MVC模式(一):統一站點入口與路由機制

     編輯:VC 教學

前言:為什麼需要統一入口?

傳統 PHP 開發中,每個功能對應一個獨立檔案(如 list.php、add.php、edit.php),導致程式碼分散、安全性難控制、架構鬆散。MVC 模式的核心思想之一是統一入口——所有請求通過單一檔案(通常是 index.php)進入,再由路由機制分發到對應的控制器。這不僅提升安全性,更奠定了整潔架構的基礎。

實現統一入口的三種常見方式

本文採用方式二(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 重寫隱藏 .php簡單但偽靜態、SEO 效果有限、不推薦
URL 重寫Apache mod_rewrite / Nginx rewrite 實現虛擬路徑標準做法、靈活強大、推薦生產環境使用
強制檔案解析Apache ForceType 將無副檔名檔案解析為 PHP無需 rewrite 模組、但靈活度較低、較少見
訪問 URL控制器動作參數
/IndexControllerindex-
/Good/testGoodControllertest-
/Good/test/id/123/type/jsonGoodControllertestid=123, type=json
/Bad/testBadControllertest-

進階擴展建議

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 層設計與資料庫抽象。

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