Nous utilisons tous DB::transaction()
pour plusieurs requêtes d'insertion. Ce faisant, un try...catch
Doit-il être placé à l'intérieur ou enveloppé? Est-il même nécessaire d'inclure un try...catch
Lorsqu'une transaction échoue automatiquement en cas de problème?
Exemple try...catch
Encapsulant une transaction:
// 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;
}
Au contraire, une DB::transaction()
enveloppant un essai ... attrape:
// Transaction
$exception = DB::transaction(function() {
// try...catch
try {
// Do your SQL here
}
catch(Exception $e) {
return $e;
}
});
return is_null($exception) ? true : false;
Ou tout simplement une transaction sans essayer ... attraper
// Transaction only
$exception = DB::transaction(function() {
// Do your SQL here
});
return is_null($exception) ? true : false;
Dans le cas où vous devez manuellement "quitter" une transaction par le code (que ce soit par une exception ou simplement en vérifiant un état d'erreur), vous ne devez pas utiliser DB::transaction()
mais plutôt envelopper votre code dans DB::beginTransaction
et 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
}
Voir le documents de transaction .
Si vous utilisez PHP7, utilisez Throwable dans catch
pour intercepter les exceptions utilisateur et les erreurs fatales.
Par exemple:
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (\Throwable $e) {
DB::rollback();
throw $e;
}
Si votre code doit pouvoir être partagé avec PHP5, utilisez Exception
et Throwable
:
DB::beginTransaction();
try {
DB::insert(...);
DB::commit();
} catch (\Exception $e) {
DB::rollback();
throw $e;
} catch (\Throwable $e) {
DB::rollback();
throw $e;
}
Vous pouvez envelopper la transaction sur try..catch ou même les inverser, voici l'exemple de code que j'avais l'habitude d'utiliser dans laravel 5 , si vous regardez au plus profond de DB:transaction()
dans Illuminate\Database\Connection
Que le même comme vous écrivez transaction manuelle,
Transaction 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;
}
afin que vous puissiez écrire votre code comme ceci, et gérer votre exception comme envoyer un message dans votre formulaire via flash ou rediriger vers une autre page. N'OUBLIEZ PAS, le retour dans la fermeture est retourné dans transaction (), donc si vous retournez redirect()->back()
, il ne sera pas redirigé immédiatement, car il est retourné à la variable qui gère la transaction.
transaction bouclée
$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;
alors l'alternative est de jeter une variable booléenne et de gérer une redirection en dehors de la fonction de transaction ou si vous devez récupérer la raison pour laquelle la transaction a échoué, vous pouvez l'obtenir de $e->getMessage()
à l'intérieur de catch(Exception $e){...}