在 MVC 中,Model 層不只是「資料庫操作」,更是業務邏輯與資料封裝的核心。設計良好的 Model 層包含三類關鍵角色:
這種分層看似繁瑣,實則職責清晰:Model ≈ 購物車中的單一商品,Manager ≈ 訂單(管理多個商品),Db ≈ 倉庫系統(底層存取)。
|- Db.php
|- Model.php
|- Manager.php
|- ModelTest1.php ~ ModelTest4.php
|- Model/
|- ClassModel.php
|- StudentModel.php
|- ClassManager.php
|- StudentManager.php
| 表名 | 欄位 | 型別 | 說明 |
|---|---|---|---|
| class | cls_id | int | 主鍵,非空 |
| cls_name | string | 班級名稱,非空 | |
| cls_address | string | 地址,可空 | |
| student | stu_id | int | 主鍵,非空 |
| stu_clsid | int | 外鍵關聯 class,非空 | |
| stu_name | string | 學生姓名,可空 |
<?php
// Model/Model.php
abstract class Model {
protected $data = []; // 欄位資料
protected $errors = []; // 驗證錯誤
// 設定屬性(支援鏈式呼叫)
public function __set($name, $value) {
$this->data[$name] = $value;
return $this;
}
// 取得屬性
public function __get($name) {
return $this->data[$name] ?? null;
}
// 轉陣列
public function toArray() {
return $this->data;
}
// 抽象驗證方法,子類必須實作
abstract public function validate();
}
?>
<?php
// Model/ClassModel.php
require_once 'Model.php';
class ClassModel extends Model {
protected $table = 'class';
protected $pk = 'cls_id';
public function validate() {
$this->errors = [];
if (empty($this->cls_name)) {
$this->errors[] = '班級名稱不可為空';
}
return empty($this->errors);
}
public function getErrors() {
return $this->errors;
}
}
?>
<?php
// Model/Manager.php
require_once '../Db.php';
abstract class Manager {
protected $db;
protected $modelClass;
public function __construct() {
$this->db = new Db();
}
// 新增實體
public function create(Model $model) {
if (!$model->validate()) return false;
$data = $model->toArray();
unset($data[$model->pk]); // 移除自增主鍵
$fields = implode(',', array_keys($data));
$values = "'" . implode("','", array_map([$this->db, 'escape'], array_values($data))) . "'";
$sql = "INSERT INTO {$model->table} ($fields) VALUES ($values)";
return $this->db->execute($sql) > 0 ? $this->db->getInsertId() : false;
}
// 依主鍵查詢
public function findById($id) {
$sql = "SELECT * FROM {$this->modelClass} WHERE {$this->pk} = $id";
$row = $this->db->fetchRow($this->db->query($sql));
if (!$row) return null;
$model = new $this->modelClass();
foreach ($row as $k => $v) $model->$k = $v;
return $model;
}
// 更新實體
public function update(Model $model) {
if (!$model->validate()) return false;
$data = $model->toArray();
$id = $data[$model->pk];
unset($data[$model->pk]);
$sets = [];
foreach ($data as $k => $v) $sets[] = "$k = '$v'";
$sql = "UPDATE {$model->table} SET " . implode(',', $sets) . " WHERE {$model->pk} = $id";
return $this->db->execute($sql) > 0;
}
// 刪除實體
public function delete($id) {
$sql = "DELETE FROM {$this->modelClass} WHERE {$this->pk} = $id";
return $this->db->execute($sql) > 0;
}
}
?>
<?php
// Model/ClassManager.php
require_once 'Manager.php';
require_once 'ClassModel.php';
class ClassManager extends Manager {
protected $modelClass = 'ClassModel';
protected $pk = 'cls_id';
}
?>
<?php
// ModelTest1.php
require_once 'Model/ClassManager.php';
require_once 'Model/StudentManager.php';
$classMgr = new ClassManager();
$studentMgr = new StudentManager();
// 新增班級
$class = new ClassModel();
$class->cls_name = '三年二班';
$class->cls_address = '教學樓 302';
$classId = $classMgr->create($class);
echo "新增班級 ID: $classId<br>";
// 新增學生
$student = new StudentModel();
$student->stu_name = '小明';
$student->stu_clsid = $classId;
$studentMgr->create($student);
// 查詢班級學生
$students = $studentMgr->findByClass($classId);
foreach ($students as $s) {
echo "學生: {$s->stu_name}<br>";
}
?>
此架構雖為教學簡化,但已具備生產級 MVC Model 層的核心骨幹,實戰中可根據業務複雜度逐步豐富(如加入快取、事務、事件機制等)。