MVC(Model-View-Controller)從桌面應用引入 Web 領域,Java 的 Model 2 架構(Struts、Spring MVC)深刻影響了 PHP 框架設計(Laravel、ThinkPHP、Yii、CodeIgniter)。但 PHP 的無狀態、請求級生命週期特性,導致傳統 MVC 在 PHP 中難以原樣照搬。本文剖析 MVC 在 PHP 的落地困境、常見誤區,並給出實用架構建議。
| 層 | 桌面 MVC | Java Model 2 (Web) | PHP 現實 |
|---|---|---|---|
| Model | 領域模型,長駐內存,狀態持久 | JavaBean/Entity,跨請求存 Session/DB | 請求結束銷毀,無法長駐,只能每請求重建 |
| View | 持續監聽 Model 變化自動更新 | JSP/模板引擎,請求時渲染一次 | 同 Java,請求渲染,無持續綁定 |
| Controller | 協調 Model/View 同步 | Dispatcher Servlet,流程轉向、參數綁定 | 同 Java,但常退化為「胖 Controller」 |
Java 中 Model 可駐留在 Session/Application 作用域,跨請求保持狀態。PHP 每請求重新啟動腳本,Model 無法在內存中持久化。常見變通:
結論:PHP 不適合傳統「富領域模型」。實際上,PHP 的 Model 往往退化為 Data Mapper / Repository / Active Record 的資料訪問層,而非包含業務邏輯的領域對象。
許多 PHP 專案的 Controller 承擔了:參數驗證、業務邏輯編排、資料庫操作、模板渲染、JSON 輸出、異常處理。這違反了單一職責原則,導致:
Paul M. Jones 提出的 ADR 更適合 Web 請求-響應模型:
| 角色 | 職責 | 對應傳統 MVC |
|---|---|---|
| Action | 處理單一 HTTP 請求:輸入驗證、調用 Domain、構建 Responder | Controller 的單個 Action 方法 |
| Domain | 核心業務邏輯:實體、值對象、領域服務、Repository 介面 | Model(但無狀態、無視圖綁定) |
| Responder | 構建 HTTP 響應:模板渲染、JSON 序列化、狀態碼、Header | View + 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
<?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;
}
}
?>
MVC 在 PHP 中的「迷思」在於強行套用有狀態的桌面模型。PHP 的請求級無狀態特性,決定了 Model 無法長駐內存,Controller 易膨脹。ADR 架構或瘦 Controller + 豐富 Service/Domain + 獨立 Responder是更務實的選擇。框架提供的工具(FormRequest、Resource、Repository、DI)正是為了解決這些痛點而設計。理解本質,靈活取捨,才能寫出可維護、可擴展的 PHP 應用。