Мы используем 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; }
Противоположность: DB::transaction()
завершает попытку … catch:
// Transaction $exception = DB::transaction(function() { // try...catch try { // Do your SQL here } catch(Exception $e) { return $e; } }); return is_null($exception) ? true : false;
Или просто транзакция без попытки … поймать
// 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, используйте Throwable в catch
для обнаружения пользовательских исключений и фатальных ошибок.
Например:
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 или даже отменить их, вот мой пример кода, который я использовал в laravel 5, если вы посмотрите глубоко внутри DB:transaction()
в Illuminate\Database\Connection
, то же самое, что вы пишете руководство сделка,
Сделка Laravel
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 return внутри закрытия возвращается в транзакции (), поэтому, если вы вернете redirect()->back()
он не будет перенаправлен немедленно, потому что он возвращается в переменной, обрабатывающей транзакцию.
Сделка Wrap
$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()
внутри catch(Exception $e){...}