web-dev-qa-db-fra.com

Laravel: Utiliser try ... catch avec DB :: transaction ()

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;
57
enchance

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 .

132
alexrussell

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;
}
17
mnv

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){...}

8
Angga Ari Wijaya