Todos usamos DB::transaction()para múltiples consultas de inserción. Al hacerlo, ¿se try...catchdebe colocar una dentro o envolverla? ¿Es incluso necesario incluir un try...catchcuándo una transacción fallará automáticamente si algo sale mal?
Ejemplo de try...catchenvoltura de una transacción:
// 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;
}
Todo lo contrario, DB::transaction()envolver un intento ... captura:
// Transaction
$exception = DB::transaction(function() {
// try...catch
try {
// Do your SQL here
}
catch(Exception $e) {
return $e;
}
});
return is_null($exception) ? true : false;
O simplemente una transacción sin intentar ... atrapar
// Transaction only
$exception = DB::transaction(function() {
// Do your SQL here
});
return is_null($exception) ? true : false;
php
laravel
transactions
mejorar
fuente
fuente

\Exception? ¿Puedo capturarlo con este genérico\Exception? ¡Genial si lo es!DB::beginTransaction()yDB:transaction()?Si usa PHP7, use Throwable in
catchpara detectar excepciones de usuario y errores fatales.Por ejemplo:
DB::beginTransaction(); try { DB::insert(...); DB::commit(); } catch (\Throwable $e) { DB::rollback(); throw $e; }Si su código debe ser compartible con PHP5, use
ExceptionyThrowable:DB::beginTransaction(); try { DB::insert(...); DB::commit(); } catch (\Exception $e) { DB::rollback(); throw $e; } catch (\Throwable $e) { DB::rollback(); throw $e; }fuente
catchbloque. Por lo tanto, un buen lugarDB::beginTransaction()es antes deltrybloque.Puede envolver la transacción sobre try..catch o incluso revertirlos, aquí mi código de ejemplo que solía usar en laravel 5, si mira profundamente
DB:transaction()enIlluminate\Database\Connectioneso, es lo mismo que escribe una transacción manual.Transacción 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; }para que pueda escribir su código de esta manera y manejar su excepción, como devolver un mensaje a su formulario a través de flash o redirigir a otra página. RECUERDE el retorno dentro del cierre se devuelve en la transacción () por lo que si lo devuelve
redirect()->back()no se redirigirá inmediatamente, porque devolvió la variable que maneja la transacción.Ajustar transacción
$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;entonces la alternativa es lanzar una variable booleana y manejar la función de redirección externa de la transacción o si necesita recuperar por qué falló la transacción, puede obtenerla desde
$e->getMessage()adentrocatch(Exception $e){...}fuente
Decidí dar una respuesta a esta pregunta porque creo que se puede resolver usando una sintaxis más simple que el intrincado bloque try-catch. La documentación de Laravel es bastante breve sobre este tema.
En lugar de usar try-catch, puede usar el
DB::transaction(){...}contenedor de esta manera:// MyController.php public function store(Request $request) { return DB::transaction(function() use ($request) { $user = User::create([ 'username' => $request->post('username') ]); // Add some sort of "log" record for the sake of transaction: $log = Log::create([ 'message' => 'User Foobar created' ]); // Lets add some custom validation that will prohibit the transaction: if($user->id > 1) { throw AnyException('Please rollback this transaction'); } return response()->json(['message' => 'User saved!']); }); };Entonces debería ver que el usuario y el registro de registro no pueden existir el uno sin el otro.
Algunas notas sobre la implementación anterior:
returnla transacción, para que pueda utilizar laresponse()devolución dentro de su devolución de llamada.throwuna excepción si desea que la transacción se revierta (o tenga una función anidada que lance la excepción automáticamente, como una excepción SQL desde dentro de Eloquent).id,updated_at,created_aty cualesquiera otros campos están disponibles después de la creación para el$userobjeto (por la duración de esta transacción). La transacción se ejecutará a través de cualquier lógica de creación que tenga. SIN EMBARGO, todo el registro se descarta cuandoAnyExceptionse lanza. Esto significa que, por ejemplo, una columna de incremento automático paraidsí se incrementa en transacciones fallidas.Probado en Laravel 5.8
fuente