Вы неправильно используете систему транзакций. Есть два способа его использования, и вы их путаете, хотя этого никогда не следует делать.
Вариант 1: закрытие транзакции
Вы можете поместить свой код в закрытие транзакции. Как только Exception
(на самом деле Throwable
) или любой тип исключения, унаследованный от этих типов , выбрасывается, транзакция будет откатываться, а обработчик закрытия будет переброшен:
DB::transaction(function () {
$model1 = MyModel::create();
// model2 will not be created if model1 couldn't be created
$model2 = MyModel::create();
});
Вы также можете заключить транзакцию с помощью try-catch, чтобы перехватить любую транзакцию:
try {
DB::transaction(function () {
$model1 = MyModel::create();
// model2 will not be created if model1 couldn't be created
$model2 = MyModel::create();
});
} catch (\Exception $e) {
Log::error('Insert failed', ['exception' => $e]);
return redirect()->back()->withInput();
}
return redirect()->route('form.success');
Вариант 2: Контроль транзакций
Или же вы можете самостоятельно контролировать логику транзакции. Но будьте осторожны, этот путь более опасен, потому что довольно легко забыть откат или фиксацию:
DB::beginTransaction();
$model1 = MyModel::create();
if ($model1->exists !== true) {
DB::rollBack();
Log::error('Insert 1 failed');
return redirect()->back()->withInput();
}
$model2 = MyModel::create();
if ($model2->exists !== true) {
DB::rollBack();
Log::error('Insert 2 failed');
return redirect()->back()->withInput();
}
DB::commit();
return redirect()->route('form.success');
По моему мнению, использование опции 2 дает намного больше кода и менее читабельно.
Кстати, Laravel использует пользовательские исключения из базы данных. Будет выброшено \Illuminate\Database\QueryException
, а не \PDOException
.