本記事では、try/catch構文と、DB::beginTransaction() および DB::transaction() の使い分けについて、具体例とともに解説します。
try/catch:例外をキャッチして適切に処理する
try/catch構文は、処理中に発生する例外(Exception)をキャッチして、アプリケーションがエラーで落ちるのを防ぐために使用します。
例:
try {
$user = User::findOrFail(1); // ユーザーが存在しない場合、例外が発生
return response()->json(['user' => $user]);
} catch (\Exception $e) {
return response()->json(['error' => 'User not found'], 404);
}
- findOrFail() は、該当するデータがない場合に ModelNotFoundException をスローします。
- catch ブロックで例外をキャッチし、適切なレスポンスを返します。
DB::beginTransaction():手動でトランザクションを管理する
トランザクションは、複数のDB操作をまとめて一つの単位として管理したいときに使います。処理が途中で失敗しても、DBを安全な状態に保てます。
例: ユーザー登録とプロフィール作成をトランザクションで管理する
use Illuminate\Support\Facades\DB;
use App\Models\User;
use App\Models\Profile;
try {
DB::beginTransaction(); // トランザクション開始
$user = User::create([
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => bcrypt('password'),
]);
Profile::create([
'user_id' => $user->id,
'bio' => 'Software Developer',
]);
DB::commit(); // 成功したら確定
return response()->json(['message' => 'User created successfully']);
} catch (\Exception $e) {
DB::rollBack(); // 失敗したらロールバック
return response()->json(['error' => 'Failed to create user'], 500);
}
解説
- DB::beginTransaction() で処理開始
- 複数の create() を行う
- 途中でエラーが出たら DB::rollBack() で巻き戻す
- 成功時のみ DB::commit() で確定
明示的な制御ができる反面、記述量が増えるデメリットあり
DB::transaction():自動でトランザクション管理してくれる便利メソッド
Laravelには DB::transaction() メソッドがあり、トランザクションを自動的に try/catch で処理してくれます。
例:自動でロールバックされるトランザクション
use Illuminate\Support\Facades\DB;
DB::transaction(function () {
$user = User::create([
'name' => 'John Doe',
'email' => 'john@example.com',
'password' => bcrypt('password'),
]);
Profile::create([
'user_id' => $user->id,
'bio' => 'Software Developer',
]);
});
メリット
- try/catchを書かなくても自動でロールバック
- コードがスッキリ
カスタムエラーハンドリングをしたいときは try/catch 併用
- エラーごとに処理を変えたい
- エラー内容をログに記録したい
- 成功後に通知やメールを送信したい
- 一時的な失敗にリトライ処理を入れたい
DB::transaction() × try/catch:高度なエラーハンドリングも可能
例:ログ出力を伴うエラーハンドリング
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
try {
$user = DB::transaction(function () {
$user = User::create([
'name' => 'Jane Doe',
'email' => 'jane@example.com',
'password' => bcrypt('password'),
]);
Profile::create([
'user_id' => $user->id,
'bio' => 'Web Designer',
]);
return $user;
});
return response()->json(['user' => $user]);
} catch (\Exception $e) {
Log::error('User creation failed: ' . $e->getMessage());
return response()->json(['error' => 'User creation failed'], 500);
}
- DB::transaction() 内で処理を行い、例外が発生すれば自動でロールバック
- catch でログにエラーを記録し、適切なレスポンスを返す
まとめ
- try/catch は例外処理を行い、エラーハンドリングに使用
- DB::beginTransaction() はデータの一貫性を保つために手動でトランザクションを管理
- DB::transaction() は try/catch を省略でき、自動でロールバックされるため簡潔に書ける