Yii 1.x 的 ActiveRecord 採用靜態模型對應資料表,需預先為每張表建立 Model 類別。但實務上常遇到:動態建立的資料表、單純資料顯示無需驗證、讀寫分離需不同模型等情境,需要執行期動態指定表名操作資料。
將以下 DTable.php 放入 protected/models/ 目錄,即可在任何位置以動態表名操作資料。
<?php
/**
* DTable - Yii 動態資料表模型
* @author zhangxugg@163.com
* @since Yii 1.1.10
*/
class DTable extends CActiveRecord {
private static $tableName;
public function __construct($table_name = '') {
if ($table_name === null) {
parent::__construct(null); // 供 model() 靜態呼叫用
} else {
self::$tableName = $table_name;
parent::__construct();
}
}
public static function model($table_name = '') {
self::$tableName = $table_name;
return parent::model(__CLASS__);
}
public function tableName() {
return self::$tableName;
}
}
?>
$memo = new DTable('{{memo}}'); // {{}} 會自動替換為表前綴
$memo->msg = 'this is content';
$memo->save();
echo $memo->id; // 取得自動遞增 ID
$memo = DTable::model('{{memo}}')->findByPk(12);
$memo->msg = "modified content";
$memo->save();
// config/main.php 需預先定義 'db-other' 元件
DTable::$db = Yii::app()->getComponent('db-other');
$memo = DTable::model('{{memo}}')->findByPk(12);
$tableName:儲存目前操作的表名,供 tableName() 回傳。new DTable('table') 建立新記錄;DTable::model('table') 取得靜態模型實例供查詢。parent::model(__CLASS__):關鍵在於傳遞 固定類別名 DTable 而非動態表名,確保 Yii 內部快取機制正常運作(以類別名為鍵)。tableName() 回傳動態表名,完成 AR 與資料表的動態繫結。attributes 由資料庫結構自動反映。rules() 為空,資料寫入前需自行驗證。relations() 為空,無法使用 with()、through 等關聯查詢。class DTable extends CActiveRecord {
private $tableName;
public function __construct($table_name = '', $scenario = 'insert') {
$this->tableName = $table_name;
parent::__construct($scenario);
}
public static function model($table_name = '') {
$model = new self($table_name, 'model'); // 特殊 scenario 區分
return $model;
}
public function tableName() {
return $this->tableName;
}
// 覆寫 getDbConnection 確保每個實例可用不同連線
public function getDbConnection() {
return isset(self::$db) ? self::$db : parent::getDbConnection();
}
}
| 場景 | 建議方案 |
|---|---|
| 固定業務資料表 | 標準 GII 產生 Model,完整驗證、關聯、行為 |
| 動態建立的日誌/統計表 | DTable 動態模型 |
| 單純資料顯示(後台報表) | DTable 或 DAO (createCommand) |
| 跨資料庫同步/遷移 | DTable + 切換 $db 元件 |
| 需關聯查詢的動態表 | 考慮建立基底 Model + 動態設定 tableName() |
DTable 為 Yii 1.x 提供了輕量級的動態表操作能力,適用於不需完整 AR 功能的簡單讀寫場景。Yii 2.0 中可直接在 Model 覆寫 tableName() 回傳動態值,或使用 yii\db\ActiveRecord::tableName() 靜態方法搭配參數實現更優雅的動態模型。