Laravel 手動・クロージャでトランザクションを張る方法

トランザクションを張る方法は二つ。

・DBのコミットやロールバック自分で書く。
・transactionメソッドを使って、クロージャの中でSQL操作を完結させる。

公式では、下記に記載されています。

 

トランザクションとは?

●簡単に言うと、トランザクションは処理のまとまりのことです。
トランザクションを開始して、コミットされるまでをひとまとまりとして処理します。
エラーが発生したり、例外が投げられた場合は処理をなかったことにして、トランザクションの開始前に戻します。

 

DBファサードを使用する準備

●DBファサードを使用することで、トランザクションを張ることができます。
DBファサードを使用するには、使用したいファイルの頭に下記のようにuse文を追加します。

use Illuminate\Support\Facades\DB;

 

手動でトランザクションを張る

●下記のように書くことで、トランザクションを張ることができます。
beginTransactionメソッドでトランザクションを開始して、commitメソッドでデータベースに反映します。

try {
   DB::beginTransaction();

   User::create([
    'name' => 'taro',
    'email' => 'hoge1@example.com',
    'password' => 'password'
   ]);

   User::create([
    'name' => 'hanako',
    'email' => 'hoge2@example.com',
    'password' => 'password'
   ]);

   DB::commit();
} catch (Throwable $e) {
   DB::rollBack();
}

DB::beginTransactionでトランザクションを開始します。
DB::commitが呼ばれるまでは、データベースに反映されません。

今回の例はUserテーブルにデータをインサートしているだけです。
もし、複数のインサート処理やいろいろな処理がある場合にcommitまで行かずに処理が止まったりすると、インサートしたデータが反映されずに処理が終わります。
こうすることで、データの整合性を保つことができます。

エラーがあった場合は、catchで掴んでロールバックします。
DB::rollBackを呼ぶことで、トランザクションをロールバックしてくれます。
これまでのデータベースの変更をトランザクションの開始時まで戻してくれます。

 

クロージャを使用してトランザクションを張る

●手動でトランザクションを張ってみましたが、指定したブロックの処理が終わったらコミットしてくれる書き方があります。
下記のように書くことで、クロージャの中の処理が終わるまでコミットされず、終わったらコミットされるようになります。

DB::transaction(function () {
  User::create([
    'name' => 'taro',
    'email' => 'hoge@example.com',
    'password' => 'password'
  ]);
});

ちなみに、引数を渡したい場合は下記のようにクロージャにuseを書くといいです。

DB::transaction(function () use($name, $email, $password) {
  User::create([
    'name' => $name,
    'email' => $email,
    'password' => $password
  ]);
});

DB::transactionを呼び出して処理をしています。
引数で渡しているクロージャの中の処理が順に行われてます。

上から順に処理が行われて、例外やエラーなどが発生しなかった場合に、データベースにインサート内容が反映されます。
例外などがあって、処理が終わらなかった場合にはデータベースにはインサートされず、ロールバックされます。