Try / Catch-Block in PHP fängt keine Ausnahme ab

97

Ich versuche, dieses Beispiel Nr. 1 von dieser Seite aus auszuführen: http://php.net/manual/en/language.exceptions.php

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    return 1/$x;
}
try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
// Continue execution
echo "Hello World\n";
?>

Anstelle der gewünschten Ausgabe erhalte ich jedoch:

0.2
Fatal error: Uncaught exception 'Exception' with message 'Division by zero.' 
in xxx:
7 Stack trace: #0 xxx(14): inverse(0) #1 {main} thrown in xxx on line 7

Die Entwicklerumgebung, die ich verwende, ist UniServer 3.5mitPHP 5.2.3

Krassi
quelle
1
Können Sie uns Ihren Code zeigen? Der einzige Fehler, den Sie machen können, um diesen Fehler zu erhalten, ist das Abfangen der falschen Ausnahme (oder keiner).
Tammo
2
Der Code ist GENAU identisch (ich habe gerade einige Zeilenumbrüche hinzugefügt) ... trotzdem habe ich den Code noch einmal in eine Testdatei kopiert und hier ist die gleiche Fehlermeldung: 0.2 Schwerwiegender Fehler: Nicht erfasste Ausnahme 'Ausnahme' mit Meldung 'Division durch Null . ' in W: \ www \ test.php: 4 Stapelverfolgung: # 0 W: \ www \ test.php (11): invers (0) # 1 {main} in W: \ www \ test.php in Zeile 4 Ich habe wirklich keine Ahnung, was dort los ist ... vielleicht fehlerhafte PHP-Konfiguration?
Krassi
1
Einige ältere Erweiterungsversionen verursachten Probleme bei der Ausnahmebehandlung. 5.2.3 ist alt und möglicherweise liegt ein Fehler hinter dem Fehler. Können Sie PHP aktualisieren? UniServer 3.5 ist auch ziemlich alt, wenn man bedenkt, dass die aktuelle Produktionsversion 5.5 ist. Ist 3.5 ein Tippfehler?
Outis
1
In den UniServer-Release-Informationen ( wiki.uniformserver.com/index.php/… ) ist 3.5 anscheinend kein Tippfehler. Aktualisieren Sie auf UniServer 5.5 und wiederholen Sie den Beispielcode.
Outis
1
outis, danke für den Tipp :). Das habe ich damals gemacht - auf XAMPP umgestellt (mag die neue Version von UniServer nicht). 3.5 ist kein Tippfehler, aber der Server hat perfekt für mich funktioniert, sodass ich mich nie darum gekümmert habe, ihn zu aktualisieren.
Krassi

Antworten:

217

Ich hatte genau dieses Problem, bei dem es so aussah, als hätte ich sogar den Namen der Ausnahme kopiert und es trotzdem nicht verstanden. Es stellte sich heraus, dass es mein dummer Fehler war, aber ich dachte, ich sollte meinen Fall hier posten, falls sich jemand anderes in der gleichen Situation befindet.

Ich hatte meine Ausnahme in meinem Namensraum genannt A und das Skript war in einem Namespace namens B . Das Problem war, dass ich A \ MyException hatte, die gleich (in PHP) \ B \ A \ MyException ist (weil sich mein Skript im Namespace B befindet !). Alles, was ich tun musste, um das Problem zu beheben, war, dem Ausnahmenamen einen Backslash (oder wie auch immer er heißt) hinzuzufügen, damit er so aussieht: \ A \ MyException

Pijusn
quelle
7
Vielen Dank für die Veröffentlichung, denn ich wäre mehrere Tage gegangen, ohne meinen Fehler zu bemerken.
Tipu
79
Dies löste mein Problem, ein einfacher Lazy-Catch-Block im Namespace-Code sollte sein catch (\Exception $e). Ohne den Backslash Exceptionist der Namespace spezifisch und wird nicht abgeglichen (oder abgefangen).
Joemaller
3
Danke, dass du das gepostet hast!
Keepkimi
2
Vielen Dank, dass Sie dies gepostet haben. Ich habe gerade die letzten Stunden damit verbracht, verrückt zu werden, warum mein Fangblock nicht funktioniert hat. Hauptgesichtspalme.
Mitch
4
Prost! Rettete meinen Tag (und Neuronen ...) :)
Gemüse
67

Eine ziemlich alte Frage, doch ...

Ich hatte auch dieses Problem (und so fand ich diesen Beitrag), aber nur ein einfaches Experiment ermöglichte es mir, die Lösung zu finden. Versuchen Sie einfach Wechsel Exceptionzu \Exception. Hat für mich gearbeitet!

BEARBEITEN:

Wie Sivann in den Kommentaren betonte, sollte die Verwendung des Namespace dasselbe tun. Stellen Sie es also einfach use \Exception as Exception;vor Ihre Klassenerklärung.

Enethion
quelle
Brillant! :) Ich würde wahrscheinlich Stunden brauchen, um das herauszufinden, habe nur nicht an Namespace gedacht. Vielen Dank!
Alexander Gilmanov
Ja! auch: "benutze \ Exception als Exception;" oben macht das gleiche.
Sivann
@ sii-anik Versuchen Sie, den Namespace so zu verwenden, wie er von sivann geschrieben wurde.
Enethion
use Exception;sollte es einfach tun
Diego Ponciano
Danke! @ Enethion
Noamway
32

Versuchen Sie , setzen catch(\Exception $e)statt catch(Exception $e). Wenn Sie einen Code verwenden, den Sie nicht sehr gut kennen, oder - insbesondere - wenn Sie ein Framework verwenden, überschreibt es möglicherweise die Standard-PHP-Ausnahme mit einer eigenen, und daher gehen Sie möglicherweise auf den falschen Pfad und erhalten das unerwünschte Ergebnis. Wenn Sie nur setzen \Exception, dann sind Sie sicher, dass Sie die Basis-PHP-Ausnahme abfangen.

Vladimir Despotovic
quelle
@crassi, hast du meinen Vorschlag ausprobiert?
Vladimir Despotovic
2
das hat es für mich
getan
20

Sie können die typischen try {} catch {} -Blöcke in PHP nicht wie in einer anderen Sprache wie C # (Csharp) verwenden.

Wenn du das tust:

try{
    //division by zero
    $number = 5/0;
}
catch(Exception $ex){
    echo 'Got it!';
}

Sie werden das "Verstanden!" Nicht sehen. Nachricht nie. Warum? Es ist nur so, weil PHP immer eine Ausnahme braucht, um "geworfen" zu werden. Sie müssen Ihren eigenen Fehlerbehandler festlegen und eine Ausnahme damit auslösen.

Siehe Funktion set_error_handler : http://php.net/manual/es/function.set-error-handler.php

Rowinson Gallego
quelle
6
Das ist nicht dasselbe;) Du musstest selbst eine Ausnahme auslösen, und das habe ich gesagt (<< Es ist nur so, weil PHP immer eine Ausnahme braucht, um "geworfen" zu werden >>) @JaredFarrish
Rowinson Gallego
Ja, aber wie ist es nicht dasselbe?
Jared Farrish
Dieser Link ist tot, aber ich fand ihn nützlich: w3schools.com/php/func_error_set_error_handler.asp
Abscheu
Löst in PHP Version 7.3.9 $number = 5/0;keine Ausnahme aus. $numberist eingestellt zu sein INF.
virtualmic
6

Meine Initiale ist jedoch, dass Sie einen Tippfehler im Namen der Ausnahme haben, die Sie abfangen / auslösen, aber wenn Ihr Code genau der gleiche ist, bin ich mir nicht sicher, was genau los ist.

Versuchen Sie die folgende Änderung des ursprünglichen Skripts und fügen Sie Ihre Ergebnisse ein. Es wird Ihnen helfen, Ihr Problem ein bisschen besser zu diagnostizieren.

<?php

//set up exception handler to report what we didn't catch
function exception_handler($exception) {

    if($exception instanceof MyException) {
        echo "you didn't catch a myexception instance\n";

    } else if($exception instanceof Exception) {
        echo "you didn't catch a exception instance\n";

    } else {
        echo "uncaught exception of type: ".gettype($exception)."\n";
    }

    echo "Uncaught exception: " , $exception->getMessage(), "\n";
}

//install the handler
set_exception_handler('exception_handler');

class MyException extends Exception {
}

function inverse($x) {
    if (!$x) {
        throw new MyException('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
    echo inverse(0) . "\n";
} catch (MyException $e) {
    echo 'Caught myexception: ',  $e->getMessage(), "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>
sfrench
quelle
4

Ich hatte das gleiche Problem mit folgenden Konfigurationen:

PHP 5.2.14 (cli) (erstellt: 12. August 2010, 17:32:30 Uhr) Copyright (c) 1997-2010 Die PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies mit eAccelerator v0.9.5. 1 , Copyright (c) 2004-2006 eAccelerator, von eAccelerator

Die Lösung besteht darin, eAccelerator entweder zu deaktivieren oder zu aktualisieren. Ich habe beide ausprobiert und beide Korrekturen haben funktioniert. Der Fehler wird hier https://eaccelerator.net/ticket/242 gemeldet (Hinweis: Firefox beschwert sich über das SSL-Zertifikat).

Jetzt laufe ich und versuche mit den folgenden Konfigurationen richtig zu fangen:

PHP 5.2.4 (cli) (erstellt: 16. Oktober 2007, 09:13:35 Uhr) Copyright (c) 1997-2007 Die PHP Group Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies mit eAccelerator v0.9.6. 1 , Copyright (c) 2004-2010 eAccelerator, von eAccelerator

Yawar
quelle
3

In Xdebug gibt es eine Einstellung:

xdebug.show_exception_trace = 1

Dies zwingt PHP, Ausnahmen auch in einem Try-Catch-Block auszugeben. Drehen Sie dies auf0

user2950254
quelle
2
In meinem Fall musste ich das xdebug-Modul vollständig deaktivieren (das Ändern von xdebug.show_exception_trace war nicht ausreichend).
Thomas Sahlin
Vielen Dank für diese Erinnerung. Ich war eine Weile gründlich verwirrt.
Brian Litzinger
3

Wenn Sie PHP 7 verwenden, benötigen Sie möglicherweise Throwable anstelle von Exception

user5528384
quelle
Dies ist ein ziemlich alter Beitrag. Sehen Sie sich das Datum des Themas an, bevor Sie sich für eine Antwort entscheiden. Außerdem ist Ihre Antwort nicht wirklich hilfreich, da sie lautet: - nicht vollständig - keine Erklärung warum
monofone
1
Die Erklärung ist, dass PHP7 Throwable anstelle von Exception verwendet. Diese Diskussion war die erste, die ich fand, als ich auf das Problem stieß und einen Beitrag leisten wollte. Kommentare wie diese sind Gründe, warum Stack nicht Community-freundlich ist.
user5528384
1
Es war nicht meine Absicht, dich zu beleidigen. Dieser Beitrag erschien in der Überprüfungswarteschlange "Erste Beiträge" und meiner Meinung nach war es nicht sinnvoll, eine Antwort auf eine ziemlich alte Frage zu veröffentlichen. Und zum Zeitpunkt des Schreibens war die Frage Throwable noch nicht einmal in der PHP-Welt erfunden. Es wäre hilfreich, wenn Sie in Ihrer Antwort schreiben, dass Throwable die von Exception (und Error) implementierte Schnittstelle ist und somit auch abgefangen werden kann. Aber es ist keine Ergänzung zu einer Ausnahme.
Monofone
1

Versuchen Sie möglicherweise, bestimmte Erweiterungen von Drittanbietern zu deaktivieren, die Sie möglicherweise installiert haben? http://bugs.php.net/bug.php?id=41744

Ziege
quelle
1

TLDR; Stellen Sie sicher, dass Sie use Exception;oben auf beiden PHP-Dateien haben

Herr Heelis
quelle
0

Ich erlebe das auch. Ich habe einen Kommentar von Rowinson Gallego gelesen, welcher Status Exception ausgelöst werden muss. Also habe ich meinen Code geändert von:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw $e;
}

in:

try
{
  $number = 5/0; //or other exception
}
catch(Exception $e)
{
  throw new Exception($e->getMessage(),$e->getCode());
}

Es klappt.

Fauzie Adriansyah
quelle