PHP hat ein Exceptionmodell ähnlich dem anderer Programmiersprachen.
Eine Exception kann in PHP geworfen (throw
) und abgefangen (catch
)
werden. Um das Abfangen potentieller Exceptions zu ermöglichen, sollte der
jeweilige Code von einem try
-Block umschlossen werden. Jeder try
-Block
muss mindestens einen zugehörigen catch
- oder finally
-Block besitzen.
Das geworfene Objekt muss eine Instanz der Klasse Exception oder einer Unterklasse von Exception sein. Der Versuch ein Objekt zu werfen, das das nicht ist, wird einen fatalen PHP-Fehler zur Folge haben.
catch
Mehrere catch
-Blöcke können verwendet werden, um verschiedene Klassen
von Exceptions abzufangen. Die normale Programmausführung (wenn keine
Exception innerhalb des try
-Blockes geworfen wird) wird nach dem
letzten in Folge definierten catch
-Block fortgesetzt. Exceptions können
innerhalb eines catch
-Blockes geworfen (oder weitergeworfen) werden.
Wenn eine Exception geworfen wird, führt PHP den Programmcode hinter der
auslösenden Anweisung nicht aus, sondern versucht, den ersten passenden
catch
-Block zu finden. Falls eine Exception nicht abgefangen wird, wird
ein fataler Fehler mit einer
"Uncaught Exception ...
"-Nachricht ausgegeben, wenn
keine Behandlung mittels set_exception_handler()
definiert wurde.
In PHP 7.1 und später kann ein catch
-Block mehrere Exceptions getrennt
durch Pipe-Zeichen (|
) angeben. Dies ist nützlich, wenn
unterschiedliche Exceptions von unterschiedlichen Klassenhierarchien gleich
behandelt werden sollen.
finally
Ab PHP 5.5 darf nach den catch
-Blöcken oder stattdessen auch ein
finally
-Block definiert werden. Egal, ob eine Exception geworfen wurde,
wird der Code innerhalb des finally
-Blocks immer nach den try
- und
catch
-Blöcken ausgeführt, bevor die normale Ausführung fortgesetzt wird.
Eine bemerkenswerte Wechselwirkung besteht zwischen dem finally
Block und einer
return
Anweisung. Wird eine return
Anweisung innerhalb der try
oder catch
Blöcke angetroffen, wird der finally
Block dennoch ausgeführt. Außerdem wird die
return
Anweisung ausgewertet, wenn sie angetroffen wird, aber das Ergebnis wird
erst nach dem finally
Block zurückgegeben. Des Weiteren wird, wenn der finally
Block ebenfalls eine return
Anweisung enthält, der Wert aus dem finally
Block
zurückgegeben.
Hinweis:
Interne PHP-Funktionen verwenden in den meisten Fällen Error-Reporting, nur moderne objektorientierte Extensions nutzen Exceptions. Fehler können allerdings einfach mittels ErrorException in eine Exception umgewandelt werden.
Die Standard PHP Library (SPL) bietet eine große Anzahl eingebauter Exceptions.
Beispiel #3 Eine Exception werfen
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division durch Null.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Exception abgefangen: ', $e->getMessage(), "\n";
}
// Ausführung fortsetzen
echo "Hallo Welt\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
0.2 Exception abgefangen: Division durch Null Hallo Welt
Beispiel #4 Exceptionbehandlung mit einem finally
-Block
<?php
function inverse($x) {
if (!$x) {
throw new Exception('Division durch Null.');
}
return 1/$x;
}
try {
echo inverse(5) . "\n";
} catch (Exception $e) {
echo 'Exception abgefangen: ', $e->getMessage(), "\n";
} finally {
echo "Erstes finally.\n";
}
try {
echo inverse(0) . "\n";
} catch (Exception $e) {
echo 'Exception abgefangen: ', $e->getMessage(), "\n";
} finally {
echo "Zweites finally.\n";
}
// Ausführung fortsetzen
echo "Hallo Welt\n";
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
0.2 Erstes finally. Exception abgefangen: Division durch Null. Zweites finally. Hallo Welt
Beispiel #5 Wechselwirkung zwischen dem finally
-Block und return
<?php
function test() {
try {
throw new Exception('foo');
} catch (Exception $e) {
return 'catch';
} finally {
return 'finally';
}
}
echo test();
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
finally
Beispiel #6 Verschachtelte Exceptions
<?php
class MyException extends Exception { }
class Test {
public function testing() {
try {
try {
throw new MyException('foo!');
} catch (MyException $e) {
// weiterwerfen der Exception
throw $e;
}
} catch (Exception $e) {
var_dump($e->getMessage());
}
}
}
$foo = new Test;
$foo->testing();
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
string(4) "foo!"
Beispiel #7 Multi catch exception handling
<?php
class MyException extends Exception { }
class MyOtherException extends Exception { }
class Test {
public function testing() {
try {
throw new MyException();
} catch (MyException | MyOtherException $e) {
var_dump(get_class($e));
}
}
}
$foo = new Test;
$foo->testing();
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
string(11) "MyException"