php - transaction - like laravel
Laravel: Usando try... catch con DB:: transaction() (3)
En el caso de que necesite ''salir'' manualmente de una transacción mediante código (ya sea mediante una excepción o simplemente comprobando un estado de error), no debería usar DB::transaction()
sino que debe envolver su código en DB::beginTransaction
y 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
}
Ver los documentos de transacción .
Todos usamos DB::transaction()
para múltiples consultas de inserción. Al hacerlo, ¿debería try...catch
dentro de él o envolverlo? ¿Es incluso necesario incluir un try...catch
cuando una transacción fallará automáticamente si algo sale mal?
Prueba de muestra try...catch
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;
}
Lo opuesto, una DB::transaction()
envolviendo un try ... catch:
// 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;
Podrías envolver la transacción en try..catch o incluso invertirla, aquí mi código de ejemplo que solía usar en laravel 5 ,, si miras en el interior de DB:transaction()
en Illuminate/Database/Connection
lo mismo que escribir manual transacción,
Transacción de 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 el mensaje a su formulario mediante flash o redirigirlo a otra página. RECUERDE return inside closure se devuelve en transaction () así que si devuelve redirect()->back()
no se redireccionará inmediatamente, porque el devuelve en la variable que maneja la transacción.
Envolver 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 la variable booleana y manejar la redirección fuera de la función de transacción o si necesita recuperar por qué la transacción falló, puede obtenerla desde $e->getMessage()
dentro de la catch(Exception $e){...}
Si usa PHP7, use Throwable en catch
para capturar 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 comparable con PHP5, use Exception
y Throwable
:
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (/Exception $e) {
DB::rollback();
throw $e;
} catch (/Throwable $e) {
DB::rollback();
throw $e;
}