複数の挿入クエリには、すべてDB::transaction()
を使用します。その際、try...catch
をその中に配置するか、それをラップする必要がありますか?何か問題が発生した場合にトランザクションが自動的に失敗する場合、try...catch
を含める必要さえありますか?
サンプルtry...catch
トランザクションのラッピング:
// try...catch
try {
// Transaction
$exception = DB::transaction(function() {
// Do your SQL here
});
if(is_null($exception)) {
return true;
} else {
throw new Exception;
}
}
catch(Exception $e) {
return false;
}
反対に、try ... catchをラップするDB::transaction()
:
// Transaction
$exception = DB::transaction(function() {
// try...catch
try {
// Do your SQL here
}
catch(Exception $e) {
return $e;
}
});
return is_null($exception) ? true : false;
または、単にtry ... catchなしのトランザクション
// Transaction only
$exception = DB::transaction(function() {
// Do your SQL here
});
return is_null($exception) ? true : false;
手動でコードを介してトランザクションを「終了」する必要がある場合(例外を介するか、単にエラー状態を確認する)、DB::transaction()
を使用するのではなく、コードをDB::beginTransaction
およびDB::commit
/DB::rollback()
:
DB::beginTransaction();
try {
DB::insert(...);
DB::insert(...);
DB::insert(...);
DB::commit();
// all good
} catch (\Exception $e) {
DB::rollback();
// something went wrong
}
トランザクションドキュメント を参照してください。
PHP7を使用する場合は、catch
で Throwable を使用して、ユーザー例外と致命的なエラーをキャッチします。
例えば:
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (\Throwable $e) {
DB::rollback();
throw $e;
}
コードをPHP5に対応させる必要がある場合は、Exception
およびThrowable
を使用します。
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
} catch (\Throwable $e) {
DB::rollback();
throw $e;
}
トランザクションをtry..catchでラップすることも、逆にすることもできます。ここでは、Illuminate\Database\Connection
のDB:transaction()
の内部を深く見ると、laravel 5で使用したサンプルコードを使用できます。手動トランザクションを書くのと同じように、
Laravel Transaction
public function transaction(Closure $callback)
{
$this->beginTransaction();
try {
$result = $callback($this);
$this->commit();
}
catch (Exception $e) {
$this->rollBack();
throw $e;
} catch (Throwable $e) {
$this->rollBack();
throw $e;
}
return $result;
}
そのため、このようなコードを記述し、フラッシュ経由でメッセージをフォームに戻す、または別のページにリダイレクトするなどの例外を処理できます。クロージャ内のREMEMBERリターンはtransaction()で返されるため、redirect()->back()
を返す場合、トランザクションを処理する変数で返されるため、すぐにはリダイレクトされません。
トランザクションをラップ
$result = DB::transaction(function () use ($request, $message) {
try{
// execute query 1
// execute query 2
// ..
return redirect(route('account.article'));
} catch (\Exception $e) {
return redirect()->back()
->withErrors(['error' => $e->getMessage());
}
});
// redirect the page
return $result;
代わりにブール変数をスローし、トランザクション関数の外部でリダイレクトを処理するか、トランザクションが失敗した理由を取得する必要がある場合は、$e->getMessage()
inside catch(Exception $e){...}
から取得できます