W3docs

throw

Das PHP-Schlüsselwort "throw" löst eine Ausnahme aus. Erfahren Sie Syntax, benutzerdefinierte Ausnahmen, Verkettung und PHP 8-Ausdrücke.

Das PHP-Schlüsselwort throw

Das Schlüsselwort throw stoppt die normale Ausführung an der Stelle, an der es aufgerufen wird, und löst eine Ausnahme aus — ein Objekt, das signalisiert, dass etwas schiefgelaufen ist. Die Kontrolle springt sofort aus der aktuellen Funktion heraus und den Aufruf-Stack hinauf, bis ein passender catch-Block gefunden wird. Wenn kein catch übereinstimmt, bricht PHP das Skript mit einem schwerwiegenden Fehler ab.

Diese Seite behandelt die Syntax von throw, wann es anstelle der Rückgabe eines Fehlerwertes verwendet werden sollte, wie integrierte und benutzerdefinierte Ausnahmen ausgelöst werden, das erneute Auslösen und Verketten von Ausnahmen sowie das PHP-8-Feature, das throw als Ausdruck nutzbar macht. Für den weiteren Kontext siehe Ausnahmen in PHP und den try/catch/finally-Ablauf.

Syntax

throw new Exception("Error message here");

throw muss einen Wert erhalten, der eine Instanz von Throwable ist — in der Praxis eine Exception (oder eine ihrer Unterklassen) oder ein Error. Der an den Konstruktor übergebene string wird zur Nachricht der Ausnahme, die später mit getMessage() ausgelesen werden kann.

Da eine ausgelöste Ausnahme den Stack abwickelt, wird jeder Code nach throw im selben Block niemals ausgeführt:

throw new Exception("stop here");
echo "this line is unreachable"; // never executes

Warum throw statt eines Fehlerwertes zurückgeben?

Die Rückgabe eines speziellen Wertes (wie false oder -1) zur Signalisierung eines Fehlers zwingt jeden Aufrufer dazu, daran zu denken, diesen zu überprüfen, und die Bedeutung des Wertes geht leicht verloren. throw macht das Ignorieren von Fehlern unmöglich: Die Ausnahme wird automatisch weitergegeben, bis sie verarbeitet wird, und enthält eine Nachricht, einen Code, einen Stack-Trace sowie die Datei und Zeile, in der sie aufgetreten ist.

Verwenden Sie throw für außergewöhnliche Bedingungen, von denen sich die aktuelle Funktion sinnvollerweise nicht erholen kann — ungültige Argumente, eine fehlgeschlagene Datenbankverbindung, eine fehlende erforderliche Datei — und lassen Sie einen übergeordneten Aufrufer entscheiden, was zu tun ist.

Ein einfaches Beispiel

Hier löst eine divide()-Funktion eine Ausnahme aus, wenn sie durch null dividieren soll, und der Aufrufer fängt sie ab:

<?php

function divide(int $numerator, int $denominator): float
{
    if ($denominator === 0) {
        throw new InvalidArgumentException("Cannot divide by zero.");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 2), PHP_EOL; // 5
    echo divide(10, 0), PHP_EOL; // throws before printing
} catch (InvalidArgumentException $e) {
    echo "Caught: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

5
Caught: Cannot divide by zero.

Der erste Aufruf gelingt und gibt 5 aus. Der zweite Aufruf löst eine Ausnahme aus, sodass sein echo niemals ausgeführt wird und die Kontrolle direkt zum catch-Block springt.

Eine benutzerdefinierte Ausnahme auslösen

Durch das Erweitern von Exception können Sie jedem Fehlertyp einen eigenen Namen geben, sodass Aufrufer genau die Fehler catchen können, die sie interessieren, und den Rest ignorieren:

<?php

class InsufficientFundsException extends Exception {}

function withdraw(float $balance, float $amount): float
{
    if ($amount > $balance) {
        throw new InsufficientFundsException(
            "Cannot withdraw $amount; balance is only $balance."
        );
    }
    return $balance - $amount;
}

try {
    echo withdraw(100, 250), PHP_EOL;
} catch (InsufficientFundsException $e) {
    echo "Declined: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

Declined: Cannot withdraw 250; balance is only 100.

Weitere Informationen zur Erweiterung von Exception finden Sie unter Benutzerdefinierte Ausnahmeklassen.

Ausnahme-Nachricht, Code und vorherige Ausnahme

Der Exception-Konstruktor akzeptiert drei Argumente — message, code und eine previous-Ausnahme. Das dritte ermöglicht es Ihnen, einen Low-Level-Fehler in einen aussagekräftigeren zu kapseln, ohne die ursprüngliche Ursache zu verlieren (dies wird als Ausnahme-Verkettung bezeichnet):

<?php

try {
    try {
        throw new RuntimeException("Disk read failed", 13);
    } catch (RuntimeException $low) {
        // Re-throw a higher-level exception, keeping the original as the cause.
        throw new Exception("Could not load config", 0, $low);
    }
} catch (Exception $e) {
    echo $e->getMessage() . PHP_EOL;                 // Could not load config
    echo "Caused by: " . $e->getPrevious()->getMessage() . PHP_EOL; // Disk read failed
    echo "Original code: " . $e->getPrevious()->getCode() . PHP_EOL; // 13
}

Ausgabe:

Could not load config
Caused by: Disk read failed
Original code: 13

Erneutes Auslösen in einem catch-Block

Sie müssen eine Ausnahme nicht vollständig dort behandeln, wo Sie sie abfangen. Ein catch-Block kann einige Aufgaben erledigen (protokollieren, Kontext hinzufügen) und dann throw erneut aufrufen, um einem äußeren Handler die endgültige Verarbeitung zu überlassen:

<?php

function loadUser(int $id): array
{
    try {
        throw new RuntimeException("Database is down");
    } catch (RuntimeException $e) {
        error_log("loadUser($id) failed: " . $e->getMessage());
        throw $e; // pass it on
    }
}

try {
    loadUser(7);
} catch (RuntimeException $e) {
    echo "Handled at top level: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

Handled at top level: Database is down

throw als Ausdruck (PHP 8+)

Seit PHP 8.0 ist throw ein Ausdruck und nicht nur eine Anweisung, sodass es an Stellen verwendet werden kann, die einen Wert erwarten — wie die Operatoren ?: und ?? oder eine Arrow-Funktion:

<?php

function getConfig(array $config, string $key): string
{
    // Throw inline when the key is missing.
    return $config[$key] ?? throw new InvalidArgumentException("Missing key: $key");
}

echo getConfig(['env' => 'prod'], 'env'), PHP_EOL; // prod

try {
    getConfig(['env' => 'prod'], 'region');
} catch (InvalidArgumentException $e) {
    echo $e->getMessage() . PHP_EOL;
}

Ausgabe:

prod
Missing key: region

Häufige Fehler

  • Auslösen ohne ein try/catch irgendwo im Stack. Eine nicht abgefangene Ausnahme wird zu einem schwerwiegenden Fehler und stoppt das Skript. Fangen Sie sie immer irgendwo ab oder registrieren Sie einen set_exception_handler()-Fallback.
  • Auslösen eines string oder array. throw erfordert ein Objekt, das Throwable implementiert; throw "oops"; ist ein Syntaxfehler.
  • Stillschweigendes Verschlucken von Ausnahmen. Ein leerer catch-Block verbirgt Fehler. Protokollieren Sie mindestens die Nachricht oder lösen Sie erneut aus.
  • Verwendung von Ausnahmen für normalen Kontrollfluss. Das Auslösen bei jeder erwarteten Verzweigung (zum Beispiel „Benutzer nicht gefunden" bei einer routinemäßigen Suche) ist langsam und verwirrend — reservieren Sie es für wirklich außergewöhnliche Fälle.

Zusammenfassung

  • throw löst ein Throwable aus und wickelt den Stack sofort bis zum nächsten passenden catch ab.
  • Bevorzugen Sie es gegenüber magischen Rückgabewerten, damit Fehler nicht stillschweigend ignoriert werden können.
  • Erstellen Sie Unterklassen von Exception, um benannte Fehlertypen zu erstellen; übergeben Sie eine previous-Ausnahme, um Ursachen zu verketten.
  • Fangen Sie ab, fügen Sie Kontext hinzu und lösen Sie erneut throw aus, damit ein äußerer Handler entscheiden kann.
  • In PHP 8+ funktioniert throw als Ausdruck innerhalb von ??, ?: und Arrow-Funktionen.

Fahren Sie mit dem try-Block, dem catch-Block und finally fort, um den vollständigen Ausnahmebehandlungszyklus zu sehen.

Übungen

Übung
Was macht die 'throw'-Anweisung in PHP?
Was macht die 'throw'-Anweisung in PHP?
Was this page helpful?