ThinkPHP 的模型是操作資料庫的核心組件,封裝了資料表對應、CRUD 操作、自動驗證/完成、關聯模型等功能。本文系統梳理模型定義、資料表映射、基本查詢、ActiveRecord 模式、自動完成/驗證及關聯模型實戰。
<?php
namespace Home\Model;
use Think\Model;
class UserModel extends Model {
// 模型屬性設定
}
?>
UserModel.class.php(與控制器同規範)/Home/Model/ 目錄Think\Model 或其子類在 /Home/Conf/config.php 設定:
'DB_TYPE' => 'mysql', 'DB_HOST' => 'localhost', 'DB_NAME' => 'database', 'DB_USER' => 'username', 'DB_PWD' => 'password', 'DB_PORT' => '3306',
// 指定表前綴(無前綴設為空字串) protected $tablePrefix = 'top_'; // 或 '' // 指定資料表名(不含前綴) protected $tableName = 'user'; // 或直接指定完整表名 protected $trueTableName = 'users';
範例:模型名 UserModel 對應表 users(無前綴)時,設定 $tablePrefix = '' 即可自動映射;若模型名不符規範,需同時設定 $tableName 或 $trueTableName。
示範環境:在 UserController 中定義 testDemo() 方法,透過 https://localhost:8999/index.php/Home/User/testDemo 存取。
$user = M('User');
$data['username'] = 'ThinkPHP';
$data['email'] = 'ThinkPHP@gmail.com';
$user->create($data);
$record = $user->add(); // 回傳插入 ID,自動過濾不存在欄位
dump($record);
$user = M('User');
// 單筆查詢
$record = $user->where('username="ThinkPHP"')->find();
dump($record);
// 取得單一欄位值
$record = $user->where('id=3')->getField('username');
dump($record);
// 多欄位回傳關聯陣列(第一欄為鍵)
$record = $user->getField('username,email'); // 鍵:username 值:email
$record = $user->getField('email,username'); // 鍵:email 值:username
$user = M('User');
$data['username'] = 'ThinkPHPSave';
$data['email'] = 'ThinkPHPSave@outlook.com';
$record = $user->where('id=3')->save($data); // 回傳影響筆數
// 物件式寫法
$user = M('User');
$user->username = 'ThinkPHP';
$user->email = 'ThinkPHP@outlook.com';
$record = $user->where('id=3')->save();
// 單欄位更新
$user->where('id=4')->setField('username', 'ThinkPHPChangeName');
// 多欄位更新
$data = array('username'=>'ThinkPHPChangeArray', 'email'=>'ThinkPHP@array.com');
$user->where('id=6')->setField($data);
$user = M('User');
$record = $user->where('id=3')->delete(); // 條件刪除
$record = $user->delete('1,2,5'); // 直接依主鍵批次刪除
ThinkPHP 實作非標準 ORM:表對應類、記錄對應物件。
$user = M("User");
$user->username = 'ThinkPHPWithActive';
$user->email = 'ThinkPHPActive@gmail.com';
$record = $user->add(); // 新增
// 查詢:支援主鍵直接 find、動態 getByXxx、多筆 select
$user->find(2); // 主鍵查詢
$user->getByUsername("jelly"); // 動態方法查詢
$user->select('1,3,8'); // 多主鍵查詢
// 更新
$user->find(21);
$user->username = 'TOPThinkChangeWithAR';
$user->save();
// 刪除
$user->delete(8); // 單筆
$user->delete('15,16'); // 批次
在 create() 建立資料物件時觸發,用於預設值填寫、密碼加密、時間戳記錄等。
// UserModel 中定義
protected $_auto = array(
array('created_at', 'date("Y-m-d H:i:s", time())', 3, 'function'),
array('updated_at', 'date("Y-m-d H:i:s", time())', 3, 'function'),
);
// 使用 D() 實例化模型(支援自動完成/驗證)
$user = D('User');
$data['username'] = "ThinkPHP";
$data['email'] = "ThinkPHP@gmail.com";
$user->create($data);
$record = $user->add();
參數說明:array(欄位, 處理內容, 條件, 類型),條件 1=新增 2=更新 3=全部,類型可為 function/callback/field。
同樣在 create() 觸發,常用於表單驗證。
// UserModel 靜態定義
protected $_validate = array(
array('username', 'require', '用戶名不能為空'),
array('email', 'email', '郵箱格式不正確'),
array('password', '6,20', '密碼長度6-20字元', 1, 'length'),
);
// 控制器處理
public function registerValidate() {
$data['username'] = $_POST['username'];
$data['email'] = $_POST['email'];
$user = D("User");
if (!$user->create($data)) {
exit($user->getError()); // 驗證失敗輸出錯誤訊息
}
echo 'validation passes';
}
支援四種關聯:HAS_ONE、BELONGS_TO、HAS_MANY、MANY_TO_MANY。模型需繼承 Think\Model\RelationModel。
// UserModel
namespace Home\Model;
use Think\Model\RelationModel;
class UserModel extends RelationModel {
protected $_link = array(
'Article' => self::HAS_MANY,
);
}
// ArticleModel
class ArticleModel extends RelationModel {
protected $_link = array(
'User' => self::BELONGS_TO,
);
}
遵循慣例(外鍵為 user_id)時無需額外設定;若自訂外鍵需指定 foreign_key。
$user = D('User');
$record = $user->relation(true)->find(4); // 同時查出該用戶所有文章
dump($record);
關聯模型讓複雜的多表查詢變得簡潔直觀,是大型應用開發的利器。