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

PHP 實戰 MVC 模式:接口定義、單例數據源、控制器與視圖分層示例

     編輯:PHP 綜合知識

場景:只讀文章展示系統

僅涉及文章列表讀取、分頁,不含發布/編輯功能。演示如何用接口約束、單例模式、依賴注入構建清晰的 MVC 結構。

接口層

<?php
// 數據操作接口
interface DataOperation {
    public function select(array $info);      // 返回文章數據
    public function selectNum(array $info);   // 返回總條數(分頁用)
}

// 數據源接口(單例入口)
interface DataSource {
    public static function getInstance();
}

// 控制器接口
interface Controller {
    public function push($key, $value);   // 註冊視圖/模型
    public function pop($key);            // 移除註冊
    public function execute($key);        // 執行分發
}

// 視圖接口
interface View {
    public function display();            // 渲染輸出
}
?>

模型層實現

數據源單例(PDO 連接)

<?php
class DataBaseSource implements DataSource {
    private static $instance = null;
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new PDO(
                'mysql:host=localhost;dbname=article;charset=utf8',
                'root', '123456',
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
        }
        return self::$instance;
    }
}
?>

抽象數據操作基類(共享連接)

<?php
abstract class DataBaseOperation implements DataOperation {
    protected $db = null;
    public function __construct() {
        $this->db = DataBaseSource::getInstance();
    }
    // 子類必須實現 select/selectNum
}
?>

具體業務類(科技頻道)

<?php
class Tech extends DataBaseOperation {
    public function select(array $info) {
        $sql = "SELECT * FROM articles WHERE category='tech' ORDER BY id DESC LIMIT :offset,:limit";
        $st = $this->db->prepare($sql);
        $st->bindValue(':offset', $info['offset'], PDO::PARAM_INT);
        $st->bindValue(':limit', $info['limit'], PDO::PARAM_INT);
        $st->execute();
        return $st->fetchAll(PDO::FETCH_ASSOC);
    }
    public function selectNum(array $info) {
        $st = $this->db->query("SELECT COUNT(*) FROM articles WHERE category='tech'");
        return $st->fetchColumn();
    }
}
?>

控制器層

<?php
class ViewController implements Controller {
    private $registry = [];
    public function push($key, $value) { $this->registry[$key] = $value; }
    public function pop($key) { unset($this->registry[$key]); }
    public function execute($key) {
        if (!isset($this->registry[$key])) {
            throw new Exception("Module '$key' not registered");
        }
        $viewClass = $this->registry[$key];
        $view = new $viewClass();   // 實例化視圖
        $view->display();
    }
}
?>

視圖層(基於 Smarty)

<?php
abstract class ArticleView implements View {
    protected $smarty;
    public function __construct() {
        $this->smarty = new Smarty();
        // $this->smarty->template_dir = ...;
    }
}

class TechArticleView extends ArticleView {
    public function display() {
        // 1. 從控制器或請求獲取參數
        $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
        // 2. 調用模型(這裡簡化,實際應通過控制器注入)
        $model = new Tech();
        $articles = $model->select(['offset'=>($page-1)*10, 'limit'=>10]);
        $total = $model->selectNum([]);
        // 3. 分配模板變量
        $this->smarty->assign('articles', $articles);
        $this->smarty->assign('pagination', [
            'total' => $total,
            'per_page' => 10,
            'current' => $page
        ]);
        // 4. 輸出
        $this->smarty->display('tech_list.tpl');
    }
}
?>

入口文件

<?php
try {
    $ctrl = new ViewController();
    $ctrl->push('tech', 'TechArticleView');
    // 可持續註冊其他頻道:$ctrl->push('sports', 'SportsArticleView');

    $mod = $_GET['mod'] ?? $_POST['mod'] ?? 'tech';
    $ctrl->execute($mod);
} catch (Exception $e) {
    // 統一異常處理:記錄日誌、顯示友好錯誤頁
    error_log($e->getMessage());
    include 'error_500.php';
}
?>

關鍵設計點總結

  • 接口先行:定義契約,實現類可隨時替換(如換 ORM、換模板引擎)。
  • 單例數據源:避免重複建立 PDO 連接,節省資源。
  • 抽象基類共享連接:子類自動獲得 $this->db,無需重複注入。
  • 控制器作為註冊中心:解耦 URL 參數與具體視圖類,支持動態擴展模塊。
  • 視圖專注渲染:不包含 SQL、業務判斷,僅負責數據組裝與模板調用。
  • 異常統一捕獲:入口文件 try-catch 保證錯誤不外露堆棧信息。

進階擴展方向

  • 引入依賴注入容器(Pimple/PHP-DI)管理對象生命周期。
  • 模型層接入 Repository 模式,進一步隔離數據庫細節。
  • 控制器採用前置/後置中間件(認證、日誌、CSRF)。
  • 視圖支援多格式響應(HTML/JSON/XML)基於 Accept 頭自動協商。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved