2012-12-19 3 views
8

Ich habe ein PHP-Skript lässt sagen während der Ausführung der Skripts löst eine Ausnahme aus. Ich möchte, dass meine PHP-Datei dort fortgesetzt wird, wo sie aufgehört hat (wo sie die Ausnahme ausgelöst hat).Resume PHP zu Ausführungsskript nach Ausnahme

Sollte ich den gleichen Ausführungscode in den "Fang" Teil des Codes?

Am Beispiel läßt ist Connects sagen mySQL es für die Verbindung fehlschlägt

function someCode(){ 
     $pdostmt = $this->prepare($this->sql); 
     if($pdostmt->execute($this->bind) !== false) { 
      if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql)) 
       return $pdostmt->fetchAll($this->fetchOption); 
      elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql)) 
       return $pdostmt->rowCount(); 
    } 
    try { 
     someCode(); 
     } 
    } catch (PDOException $e) { 
     //re-execute same code as within the try clause? 
     someCode(); 
    } 
+2

Können Sie ein Beispiel geben, was Sie zu tun versuchen? Vielleicht hilft das Refactoring. –

+5

Code, oder es ist nicht geschehen. – moonwave99

+0

Ein 'try' Block kann viele Anweisungen enthalten. Es ist möglich herauszufinden, welcher die Ausnahme ausgelöst hat, aber es ist nicht trivial. Was versuchst du zu erreichen? –

Antwort

21

Zunächst einmal sollte man sich klar machen, dass eine Ausnahme nur fatal ist, wenn es nicht gefangen wird. Das Abfangen einer Ausnahme bewirkt nicht Skriptausführung anhalten. Es stoppt lediglich den Stapelrahmen im try-Block und übergibt die Kontrolle an den catch-Block. Von dort wird das Skript weiterhin normal ausgeführt.

Durch das Abfangen der Ausnahme hier sind wir wieder noch normal Skriptausführung nachdem die Ausnahme gefangen ...

try { 
    echo "Try...\n"; 
    throw new Exception("This is an exception"); 
} catch(Exception $e) { 
    echo "Exception caught with message: " . $e->getMessage() . "\n"; 
} 

echo "Script is still running..."; 

Was Sie wollen, ist ein exception handler. Um eine Exception-Handler zu verwenden, so dass Sie jede Ausnahme nicht in try/catch Blöcke behandeln müssen Sie folgendes tun ...

function myExceptionHandler($e) { 
    echo "Uncaught exception with message: " , $e->getMessage(), "\n"; 
} 

set_exception_handler('myExceptionHandler'); // Registers the exception handler 

throw new Exception("This is Exception 1"); 
throw new Exception("This is Exception 2"); 
throw new Exception("This is Exception 3"); 
echo "The script is still running..."; 

Edit: Nach Klärung Ihrer Frage denke ich, dass ich sagen sollte Was Sie wollen, ist kein Ausnahme-Handler, aber Sie möchten überhaupt keine Ausnahmen verwenden. Was Sie versuchen zu tun, erfordert nicht, Ausnahmen zu werfen. Setzen Sie PDO nicht in den Ausnahme-Modus, wenn Sie nur den Fehler so behandeln wollen. Ausnahme sollte nur verwendet werden, um außergewöhnliche Fehler zu behandeln. Der springende Punkt einer Ausnahme ist, sicherzustellen, dass Sie Ihr Versprechen halten. Zum Beispiel, wenn Ihre Funktion verspricht, dass sie immer ein PDOStatement-Objekt zurückgibt und es einen Fall gibt, in dem das unmöglich ist, dann ist es sinnvoll, eine Ausnahme auszulösen. Dadurch weiß der Anrufer, dass wir einen Punkt erreicht haben, an dem wir unser Versprechen nicht halten können.

Was möchten Sie grundlegende Fehlerbehandlung ist ...

function someCode(){ 
     $pdostmt = $this->prepare($this->sql); 
     if($pdostmt->execute($this->bind) !== false) { 
      if(preg_match("/^(" . implode("|", array("select", "describe", "pragma")) . ") /i", $this->sql)) 
       return $pdostmt->fetchAll($this->fetchOption); 
      elseif(preg_match("/^(" . implode("|", array("delete", "insert", "update")) . ") /i", $this->sql)) 
       return $pdostmt->rowCount(); 
     } else { 
      return false; 
     } 
} 

while (someCode() === false) { 
    /* Call someCode() until you get what you want */ 
} 
+0

Also was ist der Zweck von endlich in PHP 5.5? Ich habe immer darauf geachtet, dass nach einem Catch die Ausführung fortgesetzt wird und das Script nicht angehalten wird. – MCHam

+0

@MCHam Der Zweck von 'finally' ist es zu garantieren, dass ein Codeblock ** läuft ** trotz ob eine Exception in einen' try' Block geworfen wird oder nicht und ob sie innerhalb eines 'catch' Blocks behandelt wird oder nicht. ** NUR UNCAUGHT EXCEPTIONS SIND FATAL ** – Sherif

+0

In PHP 5.5+ wenn Sie eine Rückgabeanweisung in Ihrem try-Block haben, wird es immer noch den finally-Block ausführen, bevor es tatsächlich zurückkehrt (wenn Sie nur Code nach dem catch-Block haben und von innen zurückkommen) Der try-Block führt diesen Code nicht aus. Ein finally-Block garantiert daher, dass Ihr Code aufgerufen wird, unabhängig davon, ob eine Exception behandelt wird oder nicht und unabhängig davon, ob Ihr try-Code zurückgibt oder weiterführt. – Russ

0

Sie in der Lage Zeitüberschreitung könnten den schließlich Teil der Try-Catch zu verwenden, wenn Sie nicht eine Ausnahme bei der Ausführung erhalten.

try { 
    // some crashing code 
} catch (Exception $e) { 
    //some catch code 
} finally { 
    //code that will run anyways. 
} 
+0

Ist das nicht endlich ein Feature von PHP 5.5 (also hat es in der Praxis noch niemand)? – Smar

+0

... und es wird * nicht * von dem genauen Punkt wiederaufgenommen, an dem die Ausnahme ausgelöst wurde. Es wird nur eine fest codierte Menge von Anweisungen ausgeführt. –

+0

Ja zu beiden Kommentaren. – jaudette

3

Ich gehe davon aus, dass Sie nicht in der Lage sind, die Ausnahme in der Funktion zu handhaben es geworfen wird. Wenn Sie fortfahren möchten, wo Ihre Ausnahme ausgelöst wurde, müssen Sie dort die Ausnahme behandeln. Alles andere ist schlechtes Codieren, was für Sie oder irgendjemanden, der an dem Projekt arbeitet, Verwirrung stiftet. Wir lassen die Exception in den Baum gehen, weil wir sie in der Funktion nicht selbst behandeln können, weil es Probleme mit dem Umfang gibt.

Zu Ihrem Beispiel, das ich erweitern werde. Sie sagen, dass die Operation nicht fortgesetzt werden kann, da keine Verbindung hergestellt werden kann.In Wirklichkeit wollen wir die Funktion nicht eklatant wiederholen, weil wir im Wesentlichen einen Hangpoint zum kontinuierlichen Testen der Verbindung erzeugen werden, so dass wir einen Catch-Block weiter oben im Baum verwenden, wo wir den Benutzer benachrichtigen und entscheiden können, was wir tun wollen . Dabei können wir catch-Blöcke an den richtigen Stellen verwenden, um Daten zu speichern, damit wir die Daten wiederherstellen und zu einem späteren Zeitpunkt ausführen können. In Wirklichkeit wollen wir an einem Punkt vor dem try-Block aufziehen.

Dies wird Ihnen einen viel klareren Ausführungspfad geben. Manchmal muss man eine Funktion/Methode überdenken, damit sie eine Sache und eine Sache richtig macht.

Um die Antwort auf Ihre Frage einfach und unverblümt zu setzen. Nein, es ist eine schlechte Idee, die try (ed) -Funktion im catch-Block aufzurufen und der einfache Grund ist, dass Sie nicht lange einen try-Block haben, um dort eine Ausnahme zu fangen. Ausnahmen führen zu einer sinnvolleren Fehlerbehandlung und geben dann nur wahr und falsch als Rückgabe zurück. Es bedeutet jedoch, dass Sie den ganzen Kreis im Umgang mit ihnen durchlaufen müssen.

Jetzt für ein alternatives Beispiel ... Angenommen, wir haben mehrere Server, mit denen wir eine Verbindung herstellen können, und Sie wollten die Liste ausführen, Sie würden das try/catch in eine Schleife setzen und der Catch nach dieser Ausnahme suchen Aufräumen vor dem Ausführen der nächsten Schleife. Wenn eine andere Ausnahme auftritt, werden wir die Ausnahme (erneut) werfen. Der richtige Weg, um das zu erreichen, wonach du suchst, wäre so.

function someCode() { 
    $pdostmt = $this->prepare($this->sql); 

    while($status == false) { 
     try { 
      $status = $pdostmt->execute($this->bind) 

     } catch (PDOException $e) { 
      if($e->getMessage("What ever the error message is") { 
       //Fix it here 
      } else { 
       throw $e; 
      } 
     } 
    } 
    //Do other stuff 
    return $data; //or true/false 
} 
+0

"Wenn Sie fortfahren möchten, wo Ihre Ausnahme ausgelöst wurde, müssen Sie dort die Ausnahme behandeln." - Für jeden, der einen Tl dr sucht - das ist der wichtige Teil und ist 100% der richtige Weg. –