トランザクション

CodeIgniter のデータベース抽象化により、トランザクションセーフなテーブルタイプをサポートするデータベースでトランザクションを使用できます。MySQL では、より一般的な MyISAM ではなく、InnoDB または BDB テーブルタイプを実行する必要があります。他のほとんどのデータベースプラットフォームは、ネイティブでトランザクションをサポートしています。

トランザクションに慣れていない場合は、特定のデータベースについて学ぶために、適切なオンラインリソースを見つけることをお勧めします。以下の情報は、トランザクションの基本的な理解があることを前提としています。

CodeIgniter のトランザクションへのアプローチ

CodeIgniter は、人気のあるデータベースクラス ADODB で使用されているプロセスと非常によく似たトランザクションへのアプローチを利用しています。このアプローチを選択したのは、トランザクションの実行プロセスが大幅に簡素化されるためです。ほとんどの場合、必要なのは2行のコードだけです。

従来、トランザクションは、クエリを追跡し、クエリの成功または失敗に基づいてコミットまたはロールバックするかどうかを判断する必要があるため、実装にかなりの作業が必要でした。これは、ネストされたクエリでは特に面倒です。対照的に、私たちは、これをすべて自動的に行うスマートなトランザクションシステムを実装しました(必要に応じてトランザクションを手動で管理することもできますが、実際にはメリットはありません)。

v4.3.0 以降、トランザクション中、DBDebug が true であっても、デフォルトでは例外はスローされません。

トランザクションの実行

トランザクションを使用してクエリを実行するには、$this->db->transStart() および $this->db->transComplete() メソッドを次のように使用します

<?php

$this->db->transStart();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->query('AND YET ANOTHER QUERY...');
$this->db->transComplete();

transStart()/transComplete() メソッドの間で必要なだけクエリを実行できます。それらはすべて、特定のクエリの成功または失敗に基づいてコミットまたはロールバックされます。

厳密モード

デフォルトでは、CodeIgniter はすべてのトランザクションを厳密モードで実行します。厳密モードが有効になっている場合、複数のトランザクショングループを実行しているときに、あるグループが失敗すると、後続のすべてのグループがロールバックされます。厳密モードが無効になっている場合、各グループは独立して扱われます。つまり、あるグループの失敗は他のグループには影響しません。

厳密モードは次のように無効にできます

<?php

$this->db->transStrict(false);

エラーの管理

app/Config/Database.php ファイルで DBDebug が true の場合、クエリエラーが発生すると、すべてのクエリがロールバックされ、例外がスローされます。したがって、標準のエラーページが表示されます。

DBDebug が false の場合は、次のように独自のエラーを管理できます

<?php

$this->db->transStart();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->transComplete();

if ($this->db->transStatus() === false) {
    // generate an error... or use the log_message() function to log your error
}

例外のスロー

バージョン 4.3.0 で新しく追加されました。

v4.3.0 以降、トランザクション中、DBDebug が true であっても、デフォルトでは例外はスローされません。

クエリエラーが発生したときに例外をスローする場合は、$this->db->transException(true) を使用できます

<?php

// When DBDebug in the Database Config must be true.

use CodeIgniter\Database\Exceptions\DatabaseException;

try {
    $this->db->transException(true)->transStart();
    $this->db->query('AN SQL QUERY...');
    $this->db->query('ANOTHER QUERY...');
    $this->db->query('AND YET ANOTHER QUERY...');
    $this->db->transComplete();
} catch (DatabaseException $e) {
    // Automatically rolled back already.
}

クエリエラーが発生すると、すべてのクエリがロールバックされ、DatabaseException がスローされます。

トランザクションの無効化

トランザクションはデフォルトで有効になっています。トランザクションを無効にする場合は、$this->db->transOff() を使用して無効にできます

<?php

$this->db->transOff();
$this->db->transStart();
$this->db->query('AN SQL QUERY...');
$this->db->transComplete();

トランザクションが無効になっている場合、クエリはトランザクションなしでクエリを実行する場合と同様に、自動的にコミットされます。

テストモード

必要に応じて、トランザクションシステムを「テストモード」にすることができます。これにより、クエリが有効な結果を生成した場合でも、クエリはロールバックされます。テストモードを使用するには、$this->db->transStart() メソッドの最初のパラメーターを true に設定するだけです

<?php

$this->db->transStart(true); // Query will be rolled back
$this->db->query('AN SQL QUERY...');
$this->db->transComplete();

手動でのトランザクションの実行

app/Config/Database.php ファイルで DBDebug が false の場合で、トランザクションを手動で実行する場合は、次のように実行できます

<?php

$this->db->transBegin();

$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->query('AND YET ANOTHER QUERY...');

if ($this->db->transStatus() === false) {
    $this->db->transRollback();
} else {
    $this->db->transCommit();
}

手動トランザクションを実行する場合は、$this->db->transBegin() を使用してください。 $this->db->transStart() ではありません

ネストされたトランザクション

CodeIgniter では、最も外側または最上位のトランザクションコマンドのみが実行されるように、トランザクションをネストできます。トランザクションブロック内に、必要なだけ transStart()/transComplete() または transBegin()/transCommit()/transRollback() のペアを含めることができます。CodeIgniter はトランザクションの「深さ」を追跡し、最も外側のレイヤー(深さゼロ)でのみアクションを実行します。

<?php

$this->db->transStart(); // actually starts a transaction
$this->db->query('SOME QUERY 1 ...');
$this->db->transStart(); // doesn't necessarily start another transaction
$this->db->query('SOME QUERY 2 ...');
$this->db->transComplete(); // doesn't necessarily end the transaction, but required to finish the inner transaction
$this->db->query('SOME QUERY 3 ...');
$this->db->transComplete(); // actually ends the transaction

構造がはるかに複雑な場合は、内部トランザクションがデータベースによって完全に実行されるように、最も外側のレイヤーに再び到達できるようにする必要があります。これにより、意図しないコミット/ロールバックを防ぐことができます。