So nutzen Sie try… catch-Blöcke in PHP effizient


78

Ich habe try..catch-Blöcke in meinem PHP-Code verwendet, bin mir aber nicht sicher, ob ich sie richtig verwendet habe.

Zum Beispiel sieht ein Teil meines Codes so aus:

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

Ich gruppiere also mehrere Datenbankoperationen in demselben Try / Catch-Block, da ich in der Lage sein werde, eine Ausnahme zu behandeln, wenn in einer der Transaktionen eine Ausnahme auftritt.

Ich mache das so, weil ich denke, dass es lesbarer und effizienter ist als:

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

Ich bin mir jedoch nicht sicher, ob das, was ich tue, eine gute Praxis oder nur ein fauler Weg ist, Ausnahmen zu fangen.

Ich gehe davon aus, dass eine Ausnahme, die eine spezielle Behandlung erfordert, einen eigenen try / catch-Block haben sollte, andernfalls sollte es in Ordnung sein, sie im selben try / catch zu gruppieren.

Meine Frage (n) sind also:

Gibt es einen Vorteil bei der Verwendung von Try / Catch-Blöcken pro Datenbanktransaktion? oder kann ich trotzdem problemlos mehrere Datenbanktransaktionen im selben Try / Catch-Block gruppieren?

Ist es in Ordnung, Try / Catch-Blöcke zu verschachteln? Vielen Dank!

BEARBEITEN

Die return-Anweisung diente hauptsächlich zu Demonstrationszwecken, aber ich verwende auch return-in, catch()da ich eine AJAX-Anforderung an diese Methode stelle und Javascript ein JSON-Objekt erwartet. Wenn eine Ausnahme auftritt, gebe ich ein leeres JSON-codiertes Array zurück . Ich dachte nur, dass es keinen Wert hinzufügen würde, bestimmten Code in mein Beispiel einzufügen.


Ich habe die gleiche Antwort. Es hängt davon ab, ob! Sind die DB-Transaktionen voneinander abhängig, sind sie FOREIGN KEYSbeteiligt? Hängen Transaktionen in Tabelle B von denen in Tabelle A ab? Das ist es, was Sie sich fragen müssen, um zu entscheiden, ob Sie sie gruppieren können oder nicht.
CodeAngry

Ja, Transaktionen in Tabelle B hängen von Transaktionen in Tabelle A ab. Wenn also Transaktion A fehlschlägt, sollte Transaktion B nicht ausgeführt werden. Es könnte ausgeführt werden, würde aber trotzdem eine leere Ergebnismenge zurückgeben.
ILikeTacos

6
Dann gruppiere sie! Aber denken Sie daran, Sie müssen verstehen, was und warum Sie es tun. Denken Sie einfach so ... brauche ich nach dem Werfen die nächsten Codezeilen, um sie auszuführen? Wenn nicht, lege sie in den try{}Block. Diejenigen, die ich mache ... fahren nach dem catch(){}Ende fort.
CodeAngry

Antworten:


90

Wichtige Notiz

In der folgenden Diskussion wird davon ausgegangen, dass es sich um Code handelt, der wie im obigen Beispiel strukturiert ist: Unabhängig davon, welche Alternative ausgewählt wird, führt eine Ausnahme dazu, dass die Methode logischerweise aufhört, das zu tun, was sie gerade war.


Solange Sie beabsichtigen, dasselbe zu tun, unabhängig davon, welche Anweisung im tryBlock eine Ausnahme auslöst, ist es sicherlich besser, ein einzelnes try/ zu verwenden catch. Zum Beispiel:

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

Mehrere try/ catchBlöcke sind nützlich, wenn Sie den Fehler auf eine Weise behandeln können und beabsichtigen, die genau darauf zurückzuführen ist, was ihn genau verursacht hat.

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"
    }
}

4
Vergessen Sie nicht, dass PHP5.5 Unterstützung fürfinally
Mike Mackintosh

21

Aus Gründen der Nachwelt ist die Antwort möglicherweise zu spät. Sie sollten nach dem Rückgabewert der Variablen suchen und eine Ausnahme auslösen. In diesem Fall können Sie sicher sein, dass das Programm von der Stelle, an der die Ausnahme ausgelöst wird, zum catch-Block springt. Finden Sie unten.

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();

}

9

Es ist besser lesbar, einen einzelnen Versuch Catch Block. Wenn es wichtig ist, eine Art Fehler zu identifizieren, empfehle ich, Ihre Ausnahmen anzupassen.

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

7

Es gibt keinen Grund gegen die Verwendung eines einzelnen Blocks für mehrere Operationen, da jede ausgelöste Ausnahme die Ausführung weiterer Operationen nach der fehlgeschlagenen verhindert. Zumindest solange Sie aus der abgefangenen Ausnahme schließen können, welcher Vorgang fehlgeschlagen ist. Das ist so lange es in Ordnung ist, wenn einige Operationen nicht verarbeitet werden.

Ich würde jedoch sagen, dass die Rückgabe der Ausnahme nur begrenzt sinnvoll ist. Ein Rückgabewert einer Funktion sollte das erwartete Ergebnis einer Aktion sein, nicht die Ausnahme. Wenn Sie auf die Ausnahme im aufrufenden Bereich reagieren müssen, fangen Sie die Ausnahme entweder nicht hier in Ihrer Funktion, sondern im aufrufenden Bereich ab oder lösen Sie die Ausnahme zur späteren Verarbeitung erneut aus, nachdem Sie einige Debug-Protokollierungen und dergleichen durchgeführt haben.


6

Wenn eine Ausnahme ausgelöst wird, wird die Ausführung sofort angehalten und am catch{}Block fortgesetzt . Dies bedeutet, dass es nicht auftritt , wenn Sie die Datenbankaufrufe im selben try{}Block platzieren und $tableAresults = $dbHandler->doSomethingWithTableA();eine Ausnahme $tableBresults = $dbHandler->doSomethingElseWithTableB();auslösen. Bei Ihrer zweiten Option tritt dies $tableBresults = $dbHandler->doSomethingElseWithTableB();weiterhin auf, da nach dem catch{}Block die Ausführung wieder aufgenommen wurde.

Es gibt keine ideale Option für jede Situation; Wenn Sie möchten, dass der zweite Vorgang unabhängig davon fortgesetzt wird, müssen Sie zwei Blöcke verwenden. Wenn es akzeptabel (oder wünschenswert) ist, dass die zweite Operation nicht ausgeführt wird, sollten Sie nur eine verwenden.


1

In einem einzigen Versuch-Catch-Block können Sie alles tun. Die beste Vorgehensweise besteht darin, den Fehler in einem anderen Catch-Block abzufangen, wenn Sie möchten, dass sie für bestimmte Fehler mit ihrer eigenen Nachricht angezeigt werden.


1
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();
}

0

Es ist kein Problem, mehrere Ausführungszeilen mit einem einzigen try catch-Block wie unten zu schreiben

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

In dem Moment, in dem eine Ausführung entweder in install_engineoder in der install_breakFunktion erfolgt, wird die Steuerung an die Catch-Funktion übergeben. Eine weitere Empfehlung ist, Ihre Ausnahme richtig zu essen. Das heißt, anstatt zu schreiben die('Message'), ist es immer ratsam, den Ausnahmevorgang ordnungsgemäß durchzuführen. Möglicherweise möchten Sie die die()Funktion bei der Fehlerbehandlung verwenden, nicht jedoch bei der Ausnahmebehandlung.

Wenn Sie einen Catch-Block mit mehreren Versuchen verwenden sollten Sie können sich einen Catch-Block mit mehreren Versuchen vorstellen, wenn die Ausnahme des unterschiedlichen Codeblocks unterschiedliche Ausnahmetypen anzeigen soll oder wenn Sie versuchen, eine Ausnahme aus Ihrem Catch-Block wie folgt auszulösen:

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')
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.