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 executesWarum 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: 13Erneutes 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 downthrow 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: regionHäufige Fehler
- Auslösen ohne ein
try/catchirgendwo im Stack. Eine nicht abgefangene Ausnahme wird zu einem schwerwiegenden Fehler und stoppt das Skript. Fangen Sie sie immer irgendwo ab oder registrieren Sie einenset_exception_handler()-Fallback. - Auslösen eines string oder array.
throwerfordert ein Objekt, dasThrowableimplementiert;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
throwlöst einThrowableaus und wickelt den Stack sofort bis zum nächsten passendencatchab.- 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 eineprevious-Ausnahme, um Ursachen zu verketten. - Fangen Sie ab, fügen Sie Kontext hinzu und lösen Sie erneut
throwaus, damit ein äußerer Handler entscheiden kann. - In PHP 8+ funktioniert
throwals 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.