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

Yii 1.x Query Builder: update/delete 回傳值陷阱與正確用法

     編輯:PHP 綜合知識

常見錯誤觀念

許多開發者假設 update()、delete() 回傳 true/false 表示成功/失敗,**實際上回傳的是「影響的列數」(integer)**。

回傳值行為對照

方法回傳值含義
insert()int新增的列數 (通常 1);失敗拋例外
update()int**實際更新的列數**;資料未異動時回傳 0
delete()int刪除的列數;不存在時回傳 0

錯誤示範

<?php
$command = Yii::app()->db->createCommand();
$affected = $command->update('post', ['title' => 'New Title'], 'id=1');

if ($affected > 0) {       // ❌ 陷阱:資料相同導致 0 列更新,誤判為失敗
    echo '成功';
} else {
    echo '失敗';           // 實際上可能「成功執行但無資料異動」
}
?>

正確判斷邏輯

<?php
$command = Yii::app()->db->createCommand();

try {
    // update/delete 不會因「無列影響」拋例外,只有 SQL 錯誤才拋
    $affected = $command->update('post', ['title' => 'New Title'], 'id=1');

    // 判斷 SQL 是否執行成功 (無例外即成功)
    // 如需知道是否有實際異動,檢查 $affected
    if ($affected > 0) {
        echo "已更新 {$affected} 筆資料";
    } else {
        echo "執行成功,但無資料異動 (可能條件不符或資料相同)";
    }
} catch (CDbException $e) {
    // 真正的失敗:SQL 語法錯誤、連線中斷、外鍵衝突等
    error_log("DB Error: " . $e->getMessage());
    throw new CHttpException(500, '資料庫操作失敗');
}
?>

進階:確認資料是否真正異動

若業務需區分「不存在」vs「資料相同」,需先查詢:

<?php
$command = Yii::app()->db->createCommand();

// 1. 先檢查是否存在
$exists = $command->select('1')
    ->from('post')
    ->where('id=1')
    ->queryScalar();

if (!$exists) {
    throw new CHttpException(404, '文章不存在');
}

// 2. 檢查是否需更新 (避免不必要寫入)
$current = $command->select('title')
    ->from('post')
    ->where('id=1')
    ->queryScalar();

if ($current === 'New Title') {
    return ['changed' => false, 'message' => '資料無變更'];
}

// 3. 執行更新
$affected = $command->update('post', ['title' => 'New Title'], 'id=1');
// $affected 應為 1
return ['changed' => true, 'affected' => $affected];
?>

事務包裝範例

<?php
$transaction = Yii::app()->db->beginTransaction();
try {
    $command = Yii::app()->db->createCommand();

    $affected1 = $command->update('order', ['status' => 2], 'id=100');
    $affected2 = $command->insert('order_log', [
        'order_id' => 100,
        'action' => 'confirm',
        'created_at' => date('Y-m-d H:i:s'),
    ]);

    // 這裡 $affected1 可能為 0 (狀態已是 2),但不應視為失敗
    // 關鍵是 insert 必須成功 (否則拋例外)

    $transaction->commit();
    return true;
} catch (Exception $e) {
    $transaction->rollback();
    throw $e;
}
?>

Builder 方法速查

<?php
$command = Yii::app()->db->createCommand();

// INSERT
$command->insert('user', ['name' => 'John', 'email' => 'john@example.com']);
// 回傳: 1 (成功) / 拋例外 (失敗)
// 取得自增 ID: Yii::app()->db->getLastInsertID()

// UPDATE
$command->update('user', ['name' => 'Jane'], 'id=1');
// 回傳: 影響列數 (0 表示無異動)

// DELETE
$command->delete('user', 'id=1');
// 回傳: 刪除列數 (0 表示不存在)

// 批次插入 (Yii 1.1.14+)
$command->batchInsert('user', ['name', 'email'], [
    ['Alice', 'alice@example.com'],
    ['Bob', 'bob@example.com'],
]);
// 回傳: 成功插入列數
?>

關鍵心法

「無例外即成功」;影響列數僅供業務邏輯參考,非成敗判斷依據。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved