Yii 的資料庫存取物件 (DAO) 建構在 PHP PDO 之上,提供統一的 API 支援多種資料庫系統 (MySQL、PostgreSQL、SQLite、Oracle、MSSQL 等)。核心組件包括:
return [
'components' => [
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'mysql:host=localhost;dbname=mydatabase',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
// 可選:表前綴
'tablePrefix' => 'tbl_',
// 可選:連線後自動執行 SQL
'on afterOpen' => function($event) {
$event->sender->createCommand("SET time_zone = 'UTC'")->execute();
},
],
],
];
'components' => [
'db' => [ /* 主資料庫配置 */ ],
'secondDb' => [
'class' => 'yii\db\Connection',
'dsn' => 'sqlite:/path/to/database/file',
],
],
使用方式:\Yii::$app->db (主庫)、\Yii::$app->secondDb (次庫)。
$connection = new \yii\db\Connection([
'dsn' => $dsn,
'username' => $username,
'password' => $password,
]);
$connection->open();
$connection = \Yii::$app->db;
// 查詢單行
$row = $connection->createCommand('SELECT * FROM user WHERE id=1')->queryOne();
// 查詢多行
$rows = $connection->createCommand('SELECT * FROM user')->queryAll();
// 查詢單一值
$count = $connection->createCommand('SELECT COUNT(*) FROM user')->queryScalar();
// 查詢單一欄位
$names = $connection->createCommand('SELECT name FROM user')->queryColumn();
// 單次查詢
$command = $connection->createCommand('SELECT * FROM post WHERE id=:id');
$command->bindValue(':id', $_GET['id']);
$post = $command->queryOne();
// 重複執行 (效能較佳)
$command = $connection->createCommand('DELETE FROM post WHERE id=:id');
$command->bindParam(':id', $id);
$id = 1; $command->execute();
$id = 2; $command->execute();
// INSERT
$connection->createCommand()->insert('user', [
'name' => 'Sam',
'age' => 30,
])->execute();
// 批次 INSERT
$connection->createCommand()->batchInsert('user', ['name', 'age'], [
['Tom', 30], ['Jane', 20], ['Linda', 25],
])->execute();
// UPDATE
$connection->createCommand()->update('user', ['status' => 1], 'age > 30')->execute();
// DELETE
$connection->createCommand()->delete('user', 'status = 0')->execute();
使用雙大括號語法自動處理引用與表前綴:
// 自動引用欄位名與表名
$sql = "SELECT COUNT($column) FROM {{table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
// 支援表前綴 (需配置 tablePrefix)
$sql = "SELECT COUNT($column) FROM {{%$table}}";
// 若 tablePrefix='tbl_',實際查詢 tbl_table
或使用物件方法:$connection->quoteTableName($table)、$connection->quoteColumnName($column)。
$transaction = $connection->beginTransaction();
try {
$connection->createCommand($sql1)->execute();
$connection->createCommand($sql2)->execute();
$transaction->commit();
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
$transaction1 = $connection->beginTransaction();
try {
// 外層操作
$transaction2 = $connection->beginTransaction();
try {
// 內層操作
$transaction2->commit();
} catch (\Exception $e) {
$transaction2->rollBack();
}
$transaction1->commit();
} catch (\Exception $e) {
$transaction1->rollBack();
}
Yii 提供常數對應標準隔離級別:
Transaction::READ_UNCOMMITTEDTransaction::READ_COMMITTEDTransaction::REPEATABLE_READTransaction::SERIALIZABLE$transaction = $connection->beginTransaction([
'isolationLevel' => \yii\db\Transaction::SERIALIZABLE
]);
注意:MSSQL、SQLite 需在連線層級設定隔離級別;PostgreSQL 需在交易開始後呼叫 setIsolationLevel()。
'db' => [
'class' => 'yii\db\Connection',
'dsn' => 'dsn for master',
'username' => 'master',
'password' => '',
'slaveConfig' => [
'username' => 'slave',
'password' => '',
'attributes' => [PDO::ATTR_TIMEOUT => 10],
],
'slaves' => [
['dsn' => 'dsn for slave 1'],
['dsn' => 'dsn for slave 2'],
],
]
框架自動將 SELECT 導向從庫,INSERT/UPDATE/DELETE 導向主庫。可用 $db->useMaster() 強制讀主庫,或設定 enableSlaves=false 關閉分離。
'masters' => [
['dsn' => 'master 1'], ['dsn' => 'master 2'],
],
'slaves' => [ /* 從庫陣列 */ ],
交易預設使用主庫連線;若需在從庫執行交易,呼叫 $db->slave->beginTransaction()。
$schema = $connection->getSchema();
$tables = $schema->getTableNames(); // 所有表名
$columns = $schema->getTableSchema('user')->columns; // 欄位資訊
// 建立表
$connection->createCommand()->createTable('post', [
'id' => 'pk',
'title' => 'string',
'text' => 'text',
])->execute();
// 刪除表
$connection->createCommand()->dropTable('post')->execute();
// 新增欄位
$connection->createCommand()->addColumn('post', 'author_id', 'integer')->execute();
// 主鍵查詢
$customer = Customer::findOne(10);
$customers = Customer::findAll([10, 11, 12]);
// 條件查詢
$customers = Customer::find()
->where(['age' => 30, 'status' => 1])
->andWhere('score > 100')
->orderBy('id DESC')
->limit(10)
->offset(5)
->all();
// 參數綁定
$customers = Customer::find()
->where('age=:age AND status=:status')
->addParams([':age' => 30, ':status' => 1])
->all();
// 原生 SQL
$customers = Customer::findBySql('SELECT * FROM customer WHERE age=30')->all();
// 更新/刪除
Customer::updateAll(['status' => 1], 'id = :id', [':id' => 10]);
Customer::deleteAll(['status' => 1], 'id = :id', [':id' => 10]);
$subQuery = (new \yii\db\Query())
->select('COUNT(*)')
->from('customer');
$query = (new \yii\db\Query())
->select(['id', 'count' => $subQuery])
->from('customer');
Yii DAO 提供從底層 SQL 執行到高階 ActiveRecord 的完整資料庫操作體系。掌握參數綁定、交易控制、主從分離與 Schema 管理,能構建安全、高效、可擴展的資料存取層。實務上建議:簡單查詢用 DAO/QueryBuilder,複雜業務邏輯用 ActiveRecord,結構變更用 Migration。