ActiveRecord 核心概念
- 每個 AR 類對應一張資料表 (或視圖)。
- 類屬性對應表欄位 (大小寫敏感,依資料庫 Schema)。
- 實例對應表內單行資料。
- CRUD 操作封裝為實例/靜態方法,極大簡化代碼。
定義 AR 類別
class Employee extends CActiveRecord {
// 必須實現:靜態 model() 方法
public static function model($className = __CLASS__) {
return parent::model($className);
}
// 必須實現:表名
public function tableName() {
return 'Employee';
}
// 可選:主鍵 (非 id 或複合鍵時)
public function primaryKey() {
return 'EmployeeId';
}
// 可選:關聯定義 (見教程 27)
public function relations() { return []; }
// 可選:驗證規則
public function rules() { return []; }
}
導入 AR 類別 (批量導入)
// protected/config/main.php
'import' => [
'application.models.*',
// 'application.models.forms.*',
],
基礎 CRUD 操作
1. 讀取 (查詢)
| 方法 | 用途 | 回傳 |
| find($condition, $params) | 符合條件第一行 | AR 實例 / null |
| findByPk($pk, $condition, $params) | 主鍵查詢 | AR 實例 / null |
| findByAttributes($attrs, $condition, $params) | 屬性值查詢 | AR 實例 / null |
| findBySql($sql, $params) | 自定義 SQL 查詢 | AR 實例 / null |
| findAll($condition, $params) | 所有符合行 | AR 實例陣列 |
| findAllByPk($pks, $condition, $params) | 多主鍵查詢 | AR 實例陣列 |
| findAllByAttributes($attrs, $condition, $params) | 多屬性值查詢 | AR 實例陣列 |
| findAllBySql($sql, $params) | 自定義 SQL 多行 | AR 實例陣列 |
| count($condition, $params) | 統計筆數 | 整數 |
| exists($condition, $params) | 是否存在 | 布林值 |
範例:讀取所有員工
// Controller
public function actionIndex() {
$model = Employee::model()->findAll();
$this->render('index', ['model' => $model]);
}
// View (index.php)
EmployeeId: EmployeeId; ?>
First Name: FirstName; ?>
Last Name: LastName; ?>
Title: Title; ?>
Address: Address; ?>
Email: Email; ?>
----------------------
2. 建立 (新增)
$employee = new Employee();
$employee->FirstName = 'James';
$employee->LastName = 'Shen';
$employee->Title = 'Developer';
$employee->Email = 'james.shen@example.com';
// ... 其他欄位
$employee->save(); // 自動判斷 INSERT/UPDATE
// 取得自增主鍵
echo $employee->EmployeeId;
3. 更新
$employee = Employee::model()->findByPk(1);
$employee->Title = 'Senior Developer';
$employee->save(); // 執行 UPDATE
4. 刪除
$employee = Employee::model()->findByPk(1);
$employee->delete(); // 執行 DELETE
// 或批次刪除
Employee::model()->deleteAll('Title=:title', [':title'=>'Intern']);
條件與參數詳細說明
$condition:SQL WHERE 子句字串,或陣列格式 ['column'=>value, 'column2'=>value2] (自動 AND 串接)。
$params:參數陣列,對應 $condition 中的佔位符 :param 或 ?。
- 陣列格式條件支援運算子:
['>', 'age', 18]、['in', 'id', [1,2,3]]、['like', 'name', '%John%']。
View 中存取欄位值
- 直接屬性存取:
$employee->FirstName (大小寫需與資料庫欄位一致)。
- 格式化輸出:
Yii::app()->dateFormatter->format('yyyy-MM-dd', $employee->BirthDate)。
- 關聯導航 (需定義 relations):***
$employee->manager->FirstName***。
常見問題與解決
| 問題 | 原因 | 解決 |
| Property "Employee.xxx" is not defined | 欄位名大小寫不符、或表無此欄位 | 確認資料庫 Schema、AR 類別屬性大小寫 |
| save() 返回 false | 驗證失敗、唯一鍵衝突、欄位非空違規 | 檢查 $employee->getErrors()、資料庫約束 |
| findByPk 返回 null | 主鍵值不存在、型別不符 (字串 vs 整數) | 確認參數型別、資料確實存在 |
| 關聯導航報錯 | 未定義 relations()、關聯類別名錯誤、外鍵欄位錯誤 | 檢查 relations() 定義、參考教程 27 |
最佳實踐
- 在
model() 中使用 __CLASS__ 常數,支援繼承。
- 定義
primaryKey() 當主鍵非 id 時。
- 大量資料讀取考慮
CDbDataReader 或 Query Builder 避免實例化開銷。
- 關聯查詢使用
with() 預載入 (Eager Loading) 避免 N+1 問題:Post::model()->with('author', 'comments')->findAll()。
- 業務邏輯封裝在 AR 類別方法中 (如
$employee->promote()),Controller 保持輕量。