web-dev-qa-db-fra.com

Comment utiliser efficacement try ... catch block in PHP

J'utilise des blocs try..catch dans mon code PHP), mais je ne suis pas sûr de les avoir utilisés correctement.

Par exemple, certains de mes codes ressemblent à:

 try {
      $tableAresults = $dbHandler->doSomethingWithTableA();
      $tableBresults = $dbHandler->doSomethingElseWithTableB();
 } catch (Exception $e) {
      return $e;
 }

Je regroupe donc plusieurs opérations de base de données dans le même bloc try/catch, car si une exception se produit dans l'une des transactions, je serai en mesure de la gérer.

Je le fais de cette façon parce que je pense que c'est plus lisible et efficace que:

 try {
       $tableAresults = $dbHandler->doSomethingWithTableA();
 } catch (Exception $e) {
       return $e;
 }
 try {
       $tableBresults = $dbHandler->doSomethingWithTableB();
 } catch (Exception $e) {
       return $e;
 }

Bien que, je ne suis pas sûr si ce que je fais est une bonne pratique ou juste un moyen paresseux d’attraper des exceptions.

Mon hypothèse est que ce n'est que si une exception nécessite un traitement spécial, elle devrait avoir son propre bloc try/catch, sinon le regroupement dans le même try/catch devrait être correct.

Donc, ma question est:

L'utilisation de blocs try/catch par transaction de base de données présente-t-elle un avantage? ou puis-je toujours grouper plusieurs transactions de base de données dans le même bloc try/catch sans aucun problème?

Est-ce que ça va pour imbriquer des blocs try/catch? Merci!

EDIT

La déclaration return a été utilisée principalement à des fins de démonstration, mais j'utilise également des retours dans catch() parce que je fais une demande AJAX à cette méthode, et Javascript attend un objet JSON, puis si une exception se produit, je retourne un tableau codé JSON vide.

74
ILikeTacos

note importante

La discussion suivante suppose que nous parlons de code structuré comme dans l'exemple ci-dessus: quelle que soit l'alternative choisie, une exception entraînera logiquement que la méthode cesse de faire ce qu'elle était au milieu.


Tant que vous avez l'intention de faire la même chose, quelle que soit l'instruction dans le bloc try lève une exception, il est certainement préférable d'utiliser un seul try/catch. Par exemple:

function createCar()
{
    try {
      install_engine();
      install_brakes();
    } catch (Exception $e) {
        die("I could not create a car");
    }
}

Plusieurs blocs try/catch sont utiles si vous pouvez et souhaitez gérer l’échec de manière spécifique à ce qui l’a provoquée.

function makeCocktail()
{
    try {
        pour_ingredients();
        stir();
    } catch (Exception $e) {
        die("I could not make you a cocktail");
    }

    try {
        put_decorative_umbrella();
    } catch (Exception $e) {
        echo "We 're out of umbrellas, but the drink itself is fine"
    }
}
89
Jon

Pour la postérité, la réponse peut-être trop tard. Vous devriez vérifier la valeur de retour de la variable et lever une exception. Dans ce cas, vous êtes assuré que le programme passera de l'endroit où l'exception est levée au bloc catch. Trouvez ci-dessous.

try{
   $tableAresults = $dbHandler->doSomethingWithTableA();
   if (!tableAresults) 
     throw new Exception('Problem with tableAresults');

  $tableBresults = $dbHandler->doSomethingElseWithTableB();
   if (!tableBresults) 
     throw new Exception('Problem with tableBresults');
} catch (Exception $e) {
    echo $e->getMessage();

}
21
kodepet

Il est plus lisible d'un bloc catch try simple. Si c'est important, identifiez un type d'erreur, je vous recommande de personnaliser vos exceptions.

try {
  $tableAresults = $dbHandler->doSomethingWithTableA();
  $tableBresults = $dbHandler->doSomethingElseWithTableB();
} catch (TableAException $e){
  throw $e;
} catch (Exception $e) {
  throw $e;
}
9
zongo

Il n'y a aucune raison d'utiliser un seul bloc pour plusieurs opérations, car toute exception levée empêchera l'exécution d'opérations supplémentaires après celle qui a échoué. Au moins tant que vous pouvez déterminer quelle opération a échoué avec l'exception interceptée. C’est aussi longtemps que cela fonctionne si certaines opérations sont non traitées.

Cependant, je dirais que renvoyer l'exception n'a qu'un sens limité. Une valeur de retour d'une fonction doit être le résultat attendu d'une action et non l'exception. Si vous devez réagir à l'exception dans la portée de l'appel, ne capturez pas l'exception ici dans votre fonction, mais dans la portée de l'appel, ou relancez l'exception pour un traitement ultérieur après avoir effectué une journalisation de débogage, etc.

8
arkascha

Quand une exception est levée, l'exécution est immédiatement arrêtée et continue au bloc catch{}. Cela signifie que si vous placez les appels de base de données dans le même bloc try{} Et que $tableAresults = $dbHandler->doSomethingWithTableA(); lève une exception, $tableBresults = $dbHandler->doSomethingElseWithTableB(); ne se produira pas. Avec votre deuxième option, $tableBresults = $dbHandler->doSomethingElseWithTableB(); continuera à apparaître car il se trouve après le bloc catch{}, Lorsque l'exécution a repris.

Il n'y a pas d'option idéale pour chaque situation. si vous souhaitez que la deuxième opération se poursuive malgré tout, vous devez utiliser deux blocs. S'il est acceptable (ou souhaitable) que la deuxième opération ne se produise pas, vous devez en utiliser une seule.

6
IanPudney
try
{
    $tableAresults = $dbHandler->doSomethingWithTableA();
    if(!tableAresults)
    {
        throw new Exception('Problem with tableAresults');
    }
    $tableBresults = $dbHandler->doSomethingElseWithTableB();
    if(!tableBresults) 
    {
        throw new Exception('Problem with tableBresults');
    }
} catch (Exception $e)
{
    echo $e->getMessage();
}
1
nitin kumar maurya

en un seul bloc catch try, vous pouvez faire tout ce que vous avez recommandé. La meilleure pratique consiste à intercepter l'erreur dans un bloc catch différent si vous souhaitez qu'ils s'affichent avec leur propre message pour des erreurs particulières.

1
Amar Agrawal

Il n'y a aucun problème pour écrire plusieurs lignes d'exécution avec un seul bloc catch try comme ci-dessous

try{
install_engine();
install_break();
}
catch(Exception $e){
show_exception($e->getMessage());
}

Au moment où une exécution se produira dans la fonction install_engine Ou install_break, Le contrôle sera passé à la fonction catch. Une autre recommandation est de manger votre exception correctement. Ce qui signifie qu'au lieu d'écrire die('Message'), il est toujours conseillé d'avoir un processus d'exception correctement. Vous pouvez penser à utiliser la fonction die() dans la gestion des erreurs mais pas dans la gestion des exceptions.

Quand utiliser plusieurs blocs catch try Vous pouvez penser à plusieurs blocs catch try si vous souhaitez que l'exception de bloc de code différent affiche un type d'exception différent ou si vous essayez de lever une exception à partir de votre bloc catch, comme ci-dessous:

try{
    install_engine();
    install_break();
    }
    catch(Exception $e){
    show_exception($e->getMessage());
    }
try{
install_body();
Paint_body();
install_interiour();
}
catch(Exception $e){
throw new exception('Body Makeover faield')
}

Pour plus de détails sur l'utilisation de try block dans différents cas, vous pouvez vous référer à mon blog sur PHP Try Catch

0