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

PHP 中的 MVC 迷思:模型層難落地、Controller 異化與實用架構建議

     編輯:PHP 相關知識

前言

MVC(Model-View-Controller)從桌面應用引入 Web 領域,Java 的 Model 2 架構(Struts、Spring MVC)深刻影響了 PHP 框架設計(Laravel、ThinkPHP、Yii、CodeIgniter)。但 PHP 的無狀態、請求級生命週期特性,導致傳統 MVC 在 PHP 中難以原樣照搬。本文剖析 MVC 在 PHP 的落地困境、常見誤區,並給出實用架構建議。

MVC 原型與 Web 異化

層桌面 MVCJava Model 2 (Web)PHP 現實
Model領域模型,長駐內存,狀態持久JavaBean/Entity,跨請求存 Session/DB請求結束銷毀,無法長駐,只能每請求重建
View持續監聽 Model 變化自動更新JSP/模板引擎,請求時渲染一次同 Java,請求渲染,無持續綁定
Controller協調 Model/View 同步Dispatcher Servlet,流程轉向、參數綁定同 Java,但常退化為「胖 Controller」

PHP 中 Model 的核心困境

Java 中 Model 可駐留在 Session/Application 作用域,跨請求保持狀態。PHP 每請求重新啟動腳本,Model 無法在內存中持久化。常見變通:

  • 請求級重建:每請求從 DB 讀取、實例化 Model,用完丟棄。開銷大,但符合 PHP 生命週期。
  • Session 序列化:Model 序列化存 Session,下請求反序列化。效能差、併發鎖問題、序列化兼容性風險。
  • 靜態/單例緩存:靜態屬性緩存 Model 實例。僅進程內有效(PHP-FPM 多進程不共享),需配合 Redis/APCu。

結論:PHP 不適合傳統「富領域模型」。實際上,PHP 的 Model 往往退化為 Data Mapper / Repository / Active Record 的資料訪問層,而非包含業務邏輯的領域對象。

常見誤區:Controller 膨脹

許多 PHP 專案的 Controller 承擔了:參數驗證、業務邏輯編排、資料庫操作、模板渲染、JSON 輸出、異常處理。這違反了單一職責原則,導致:

  • 難以單元測試(依賴 HTTP 請求、資料庫)。
  • 代碼複用差(邏輯綁定在 Action 中)。
  • 維護成本高(幾百行的 Action 很常見)。

實用架構建議:Action-Domain-Responder (ADR)

Paul M. Jones 提出的 ADR 更適合 Web 請求-響應模型:

角色職責對應傳統 MVC
Action處理單一 HTTP 請求:輸入驗證、調用 Domain、構建 ResponderController 的單個 Action 方法
Domain核心業務邏輯:實體、值對象、領域服務、Repository 介面Model(但無狀態、無視圖綁定)
Responder構建 HTTP 響應:模板渲染、JSON 序列化、狀態碼、HeaderView + Controller 部分輸出邏輯

代碼結構範例

src/
├── Action/
│   └── UserRegisterAction.php
├── Domain/
│   ├── Entity/
│   │   └── User.php
│   ├── Repository/
│   │   └── UserRepositoryInterface.php
│   │   └── PdoUserRepository.php
│   └── Service/
│       └── UserRegistrationService.php
├── Responder/
│   └── JsonResponder.php
│   └── HtmlResponder.php
└── Infrastructure/
    └── Database.php

Action 範例

<?php
class UserRegisterAction {
    public function __construct(
        private UserRegistrationService $service,
        private JsonResponder $responder
    ) {}

    public function __invoke(array $input): string {
        // 1. 輸入驗證
        $data = $this->validate($input);
        // 2. 調用領域服務
        $user = $this->service->register($data);
        // 3. 構建響應
        return $this->responder->respond($user, 201);
    }
    
    private function validate(array $input): array {
        // 使用驗證庫或手動檢查
        return $input;
    }
}
?>

現代 PHP 框架的實際做法

  • Laravel:Controller → FormRequest(驗證) → Service/Action(業務) → Resource/Response(輸出)。支援依賴注入、契約、Repository 模式。
  • Symfony:Controller 瘦化,業務邏輯在 Service 層,使用 Doctrine Entity/Repository,響應用 View/Serializer。
  • API Platform:資源導向,自動生成 CRUD,業務邏輯在 State Processor/Provider。

最佳實踐原則

  1. Controller/Action 保持瘦:僅負責 HTTP 協議轉換(輸入→數據、數據→響應)。
  2. 業務邏輯下沉到 Service/Domain:無框架依賴、可單獨測試、可複用。
  3. 資料訪問抽象為 Repository:介面在 Domain,實現 Infrastructure,便於測試替換。
  4. 輸出邏輯封裝為 Responder/Resource:JSON API 用 Resource,HTML 用 View/Template。
  5. 避免在 Model/Entity 中注入服務:實體應為純數據結構,行為放在 Domain Service。
  6. 使用依賴注入容器:管理對象生命週期、解耦依賴。

總結

MVC 在 PHP 中的「迷思」在於強行套用有狀態的桌面模型。PHP 的請求級無狀態特性,決定了 Model 無法長駐內存,Controller 易膨脹。ADR 架構或瘦 Controller + 豐富 Service/Domain + 獨立 Responder是更務實的選擇。框架提供的工具(FormRequest、Resource、Repository、DI)正是為了解決這些痛點而設計。理解本質,靈活取捨,才能寫出可維護、可擴展的 PHP 應用。

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