トランザクション(try,catch,rollback)の実装【CakePHP4】

DataBaseの絡むプログラムを実装するには、整合性の保持のために、エラーが出たら処理前の状態に戻す(ロールバックする)必要性があります。

今回は、これをCakePHPで実装する方法を解説します。

以下のように簡単に実装できます。

実装例

以下、コードの例です。

//src/Controller/SamplesController.php

<?php
use Cake\Datasource\ConnectionManager;

class SamplesController extends AppController
{

    //トランザクション開始
    $connection = ConnectionManager::get('default');
    $connection->begin();

    try {
       //処理・・・

       //エラーが発生していなければ処理を実行
       $connection->commit();
    }catch(\Exception $e) {
       //例外処理・・・

       //ロールバック
       $connection->rollback();
    }

}

try,catchと組み合わせて、異常時にはrollbackすることで簡単に実装できます。

DBへのデータ保存を行う際には、不整合が生じないように必ず実装するようにしましょう。

保存処理について ※2023年5月4日追記

save()だとrollback処理が走らない・・・。

保存処理には、save()を使うのが一般的ですが、上記のようなトランザクション処理には不適切です。

これは、save()は失敗時に単にfalseを返してしまうためです。

失敗時にはExceptionをthrowしてもらわないと、rollback処理が走らないので、先述のコードが無駄になってしまいます。

saveOrFail()を使おう

saveOrFail()を使えば、保存に失敗した際にはExceptionがthrowされるので、ロールバックが走ります。

先述のコードのトランザクション部分に当てはめると下記のようになります。

//トランザクション開始
    $connection = ConnectionManager::get('default');
    $connection->begin();

    try {
       //処理・・・
      
       //下記のsave()だと、保存に失敗してもrollbackが走らない。
       //$samplesTable->save($data);

       //saveOrFail()を使う。
       $samplesTable->saveOrFail($data);

        //エラーが発生していなければ処理を実行
       $connection->commit();

    }catch(\Exception $e) {
       //例外処理・・・

       //ロールバック
       $connection->rollback();
    }

参考

CakePHP 4.x Strawberry Cookbook:データベースの基本

コメント

タイトルとURLをコピーしました