首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Yii Framework 教程 (24):DAO 實戰範例 - 底層資料庫操作與交易控制

     編輯:PHP 綜合知識

DAO 核心類別回顧

  • CDbConnection:連線管理、交易控制
  • CDbCommand:SQL 執行、參數綁定
  • CDbDataReader:前向唯讀游標
  • CDbTransaction:交易物件

範例場景:Employee 表 CRUD 與交易

使用 Chinook 資料庫 Employee 表,欄位:EmployeeId, LastName, FirstName, Title, ReportsTo, BirthDate, HireDate, Address, City, State, Country, PostalCode, Phone, Fax, Email。

1. 建立資料庫連線


// 方式一:獨立連線 (短連線)
$connection = new CDbConnection(
    'mysql:host=localhost;dbname=chinook',
    'root',
    'password'
);
$connection->active = true; // 開啟連線
// ... 操作
$connection->active = false; // 關閉連線

// 方式二:應用組件連線 (推薦,單例共享)
// main.php 已配置 'db' 組件
$connection = Yii::app()->db; // 自動連線 (除非 autoConnect=false)

2. 執行 SQL 語句 (CDbCommand)

建立命令物件


$command = $connection->createCommand($sql);
// 或
$command = $connection->createCommand()
    ->select('*')
    ->from('Employee')
    ->where('EmployeeId=:id', [':id'=>1]);

查詢方法

方法回傳適用場景
queryAll()陣列的陣列 (所有行)小結果集完整載入
queryRow()單行陣列預期單行結果
queryColumn()單欄位值陣列僅需一欄位
queryScalar()單一純量值COUNT(*), MAX(id) 等
query()CDbDataReader大結果集流式處理

參數綁定 (防 SQL 注入)


// 命名參數
$command = $connection->createCommand(
    "SELECT * FROM Employee WHERE LastName=:name AND Country=:country"
);
$command->bindParam(':name', $lastName, PDO::PARAM_STR);
$command->bindParam(':country', $country, PDO::PARAM_STR);
// 或一次綁定
$command->bindValues([':name'=>$lastName, ':country'=>$country]);

// 位置參數
$command = $connection->createCommand(
    "INSERT INTO Employee (LastName, FirstName, Email) VALUES (?, ?, ?)"
);
$command->bindValues([$lastName, $firstName, $email]);

異動操作 (INSERT/UPDATE/DELETE)


$affected = $command->execute(); // 回傳影響行數
// INSERT 後取得自增 ID
$lastId = $connection->getLastInsertId();

3. 交易控制 (CDbTransaction)


$transaction = $connection->beginTransaction();
try {
    // 多步操作
    $connection->createCommand()->insert('Employee', [
        'LastName' => 'Doe',
        'FirstName' => 'John',
        'Email' => 'john.doe@example.com',
    ])->execute();
    
    $connection->createCommand()->update('Employee', [
        'Title' => 'Senior ' . $oldTitle
    ], 'EmployeeId=:id', [':id'=>$id])->execute();
    
    $transaction->commit();
} catch (Exception $e) {
    $transaction->rollBack();
    throw $e;
}

4. CDbDataReader 流式讀取大量資料


$command = $connection->createCommand('SELECT * FROM Employee');
$reader = $command->query(); // 回傳 CDbDataReader

while ($reader->read()) {
    $row = $reader->getAttributes(); // 當前行關聯陣列
    // 處理單行,記憶體不累積
    processEmployee($row);
}
$reader->close(); // 釋放資源

完整 Controller 範例


class SiteController extends CController {
    public function actionIndex() {
        $model = [];
        $connection = Yii::app()->db;
        
        // 參數化查詢
        $command = $connection->createCommand()
            ->select('EmployeeId, FirstName, LastName, Title, Email')
            ->from('Employee')
            ->where('ReportsTo IS NULL'); // 最高層主管
        
        $dataReader = $command->query();
        foreach ($dataReader as $row) {
            $emp = new DataModel();
            $emp->employeeId = $row['EmployeeId'];
            $emp->firstName = $row['FirstName'];
            $emp->lastName = $row['LastName'];
            $emp->title = $row['Title'];
            $emp->email = $row['Email'];
            $model[] = $emp;
        }
        
        $this->render('index', ['model' => $model]);
    }
}

DataModel 定義 (可選)


class DataModel {
    public $employeeId;
    public $firstName;
    public $lastName;
    public $title;
    public $address;
    public $email;
}

關鍵提示

  1. 永遠使用參數綁定:絕不拼接 SQL 字串,防注入、利用預備語句快取。
  2. 交易邊界最小化:僅包含必要操作,避免長交易鎖定資源。
  3. 大結果集用 CDbDataReader:避免 queryAll() 佔滿記憶體。
  4. 錯誤處理:DAO 操作拋出 CDbException,Controller 層統一捕獲轉友善訊息。
  5. 連線共享:優先使用 Yii::app()->db,避免重複建立連線開銷。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved