W3docs

getPrevious()

Die PHP-Funktion getPrevious() gibt die vorherige Exception zurück, die beim Erstellen der aktuellen übergeben wurde. Alles über Exception-Chaining.

Einführung

Exception::getPrevious() gibt die Exception zurück, die als drittes Argument an einen PHP-Exception-Konstruktor übergeben wurde — also die Exception, die die aktuelle verursacht hat. Sie ist in der Basisklasse Exception (und Error) definiert, sodass jeder PHP-Exception-Typ sie erbt.

Diese Seite erklärt, was getPrevious() zurückgibt, wie man eine Kette von „gewrappten" Exceptions aufbaut, wie man diese Kette durchläuft und welche häufigen Fehler zu vermeiden sind.

Syntax und Rückgabewert

final public Throwable::getPrevious(): ?Throwable
  • Parameter: keine.
  • Rückgabe: das vorherige Throwable (eine Exception oder ein Error), sofern eines gesetzt wurde, andernfalls null.
  • Die Methode ist final, kann also nicht in eigenen Exception-Unterklassen überschrieben werden.

Die „vorherige" Exception wird gesetzt, wenn eine Exception mit einem dritten Argument erzeugt wird:

throw new RuntimeException("High-level failure", 0, $originalException);
//                          message            ^code  ^previous

Einfaches Beispiel

Wenn eine Exception erneut geworfen wird, sollte die ursprüngliche als drittes Konstruktorargument übergeben werden, damit der Kontext nicht verloren geht:

<?php
try {
    try {
        throw new Exception("Inner error");
    } catch (Exception $inner) {
        // Wrap the low-level error in a more meaningful one,
        // keeping the original as "previous".
        throw new Exception("Outer error", 0, $inner);
    }
} catch (Exception $e) {
    echo "Caught: " . $e->getMessage() . "\n";

    $previous = $e->getPrevious();
    if ($previous !== null) {
        echo "Caused by: " . $previous->getMessage() . "\n";
    }
}
?>

Ausgabe:

Caught: Outer error
Caused by: Inner error

getPrevious() gibt das übergebene $inner-Objekt zurück, sodass dessen Nachricht, Code oder Stack-Trace genauso ausgelesen werden können wie bei jeder anderen Exception.

Warum Exceptions überhaupt wrappen?

Ein verbreitetes Muster ist, eine technische Low-Level-Exception (z. B. eine fehlgeschlagene Datenbankabfrage, eine fehlende Datei) abzufangen und eine domänenspezifische High-Level-Exception zu werfen — ohne dabei die ursprüngliche Ursache zu verwerfen:

<?php
function loadUser(int $id): array
{
    try {
        // Pretend this talks to a database and fails.
        throw new RuntimeException("SQLSTATE[HY000]: connection refused");
    } catch (RuntimeException $dbError) {
        // Callers care about "could not load user", not SQL internals,
        // but we keep the SQL error available via getPrevious().
        throw new RuntimeException("Unable to load user #$id", 0, $dbError);
    }
}

try {
    loadUser(42);
} catch (RuntimeException $e) {
    echo $e->getMessage() . "\n";
    echo "Root cause: " . $e->getPrevious()->getMessage() . "\n";
}
?>

Ausgabe:

Unable to load user #42
Root cause: SQLSTATE[HY000]: connection refused

So bleiben High-Level-Fehlermeldungen übersichtlich, während technische Details für Logging und Debugging erhalten bleiben.

Die vollständige Exception-Kette durchlaufen

Eine vorherige Exception kann selbst eine vorherige Exception haben. Um die gesamte Kette zu untersuchen, wird solange eine Schleife ausgeführt, wie getPrevious() einen Nicht-null-Wert zurückgibt:

<?php
$a = new Exception("Level 1: low-level cause");
$b = new Exception("Level 2: mid-level wrapper", 0, $a);
$c = new Exception("Level 3: top-level error", 0, $b);

$current = $c;
while ($current !== null) {
    echo $current->getMessage() . "\n";
    $current = $current->getPrevious();
}
?>

Ausgabe:

Level 3: top-level error
Level 2: mid-level wrapper
Level 1: low-level cause

Häufige Fallstricke

  • Keine vorherige Exception ergibt null. Wird eine Exception ohne drittes Argument erzeugt, gibt getPrevious() null zurück. Vor dem Aufruf von Methoden auf dem Ergebnis immer mit !== null (oder einer Schleife) prüfen.
  • Das dritte Konstruktorargument ist die vorherige Exception, nicht der Code. Die Signatur lautet new Exception($message, $code, $previous). Ein häufiger Fehler ist, die vorherige Exception an zweiter Stelle zu übergeben, wo PHP einen Integer-Code erwartet.
  • Es ist schreibgeschützt. Es gibt kein setPrevious(). Die Kette wird zur Konstruktionszeit festgelegt; die Ursache muss also beim Erstellen der wrappenden Exception übergeben werden.
  • var_dump($e) zeigt die Kette bereits an. Wird eine nicht abgefangene Exception in einen string umgewandelt (oder von PHP ausgegeben), wird die „Caused by"-/Vorgänger-Exception-Spur automatisch einbezogen — getPrevious() ist für den Fall gedacht, dass die Kette im Code untersucht werden soll.

Verwandte Methoden

getPrevious() ist eine von mehreren Inspektionsmethoden, die jede PHP-Exception bereitstellt:

Einen umfassenden Überblick über try/catch und benutzerdefinierte Exception-Klassen bietet PHP Exceptions.

Zusammenfassung

getPrevious() gibt die Exception zurück, die die aktuelle verursacht hat, und ermöglicht so Exception-Chaining: eine Low-Level-Exception abfangen, eine aussagekräftige High-Level-Exception werfen und dabei die ursprüngliche Ursache für das Debugging bewahren. Wurde keine vorherige Exception gesetzt, gibt die Methode null zurück — darauf sollte vor der Verwendung des Ergebnisses geprüft oder eine Schleife verwendet werden.

Übungen

Übung
Was macht die PHP-Funktion getPrevious()?
Was macht die PHP-Funktion getPrevious()?
Was this page helpful?