W3docs

try

Lernen Sie, wie PHP try/catch/finally Ausnahmen behandelt. Behandelt mehrere catch-Blöcke, Union-Typen, Weiterwerfen und häufige Fallstricke.

Das PHP-Schlüsselwort try

Das Schlüsselwort try markiert einen Codeblock, der eine Exception auslösen könnte — ein Objekt, das signalisiert, dass etwas schiefgelaufen ist und die normale Ausführung nicht fortgesetzt werden kann. Wenn innerhalb eines try-Blocks eine Exception ausgelöst wird, stoppt PHP die Ausführung des restlichen Blocks und sucht nach einem passenden catch-Block, um sie zu behandeln. Ein optionaler finally-Block wird danach ausgeführt, unabhängig davon, was passiert ist.

Diese Seite behandelt die Syntax von try/catch/finally, wie mehrere catch-Blöcke zugeordnet werden, das gleichzeitige Abfangen mehrerer Exception-Typen, das Weiterwerfen und die häufigsten Fallstricke. Wenn Sie neu im Umgang mit dem Auslösen von Fehlern sind, lesen Sie zuerst Exceptions in PHP.

Syntax

try {
  // Code that may throw an exception
} catch (ExceptionType $e) {
  // Code that runs if an exception of ExceptionType (or a subclass) is thrown
} finally {
  // Optional: always runs, whether or not an exception was thrown
}

Auf einen try-Block muss mindestens ein catch-Block, ein finally-Block oder beides folgen — ein try allein ist ein Syntaxfehler. Die Variable in catch (ExceptionType $e) enthält das ausgelöste Exception-Objekt, das Sie mit Methoden wie $e->getMessage() abfragen können.

Ein erstes Beispiel

Die folgende Funktion löst eine Exception aus, wenn sie gebeten wird, durch null zu dividieren. Der try-Block ruft sie auf, der catch-Block meldet das Problem, und finally wird immer ausgeführt:

<?php

function divide($dividend, $divisor)
{
  if ($divisor == 0) {
    throw new Exception("Cannot divide by zero.");
  }
  return $dividend / $divisor;
}

try {
  $result = divide(10, 0);
  echo $result;            // skipped — divide() threw before returning
} catch (Exception $e) {
  echo "Error: " . $e->getMessage() . PHP_EOL;
} finally {
  echo "Done." . PHP_EOL;
}

Ausgabe:

Error: Cannot divide by zero.
Done.

Beachten Sie, dass echo $result; niemals ausgeführt wird: Sobald divide(10, 0) eine Exception auslöst, springt die Kontrolle direkt zum catch-Block. Der finally-Block wird danach ausgeführt. Wenn Sie stattdessen divide(10, 2) aufrufen, wird keine Exception ausgelöst, der try-Block gibt 5 aus, und finally gibt trotzdem Done. aus.

Mehrere catch-Blöcke

Auf ein einzelnes try können mehrere catch-Blöcke folgen. PHP überprüft sie von oben nach unten und führt den ersten aus, dessen Typ mit der ausgelösten Exception übereinstimmt (Übereinstimmung umfasst auch Unterklassen). Listen Sie spezifischere Typen vor allgemeineren auf — ein führendes catch (Exception $e) würde alles darunter verschlucken.

<?php

try {
  $value = "5";
  if (!is_int($value)) {
    throw new TypeError("Expected an integer.");
  }
} catch (TypeError $e) {
  echo "Type problem: " . $e->getMessage() . PHP_EOL;
} catch (Exception $e) {
  echo "Other problem: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

Type problem: Expected an integer.

Mehrere Typen in einem Block abfangen

Wenn zwei Exception-Typen auf die gleiche Weise behandelt werden sollen, verbinden Sie sie mit einem senkrechten Strich (|) — eine in PHP 7.1 hinzugefügte Funktion — anstatt den Block zu duplizieren:

<?php

try {
  throw new RuntimeException("Network timed out.");
} catch (RuntimeException | LogicException $e) {
  echo "Handled: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

Handled: Network timed out.

Verhalten von finally

Der finally-Block wird selbst dann ausgeführt, wenn der try- oder catch-Block ein return enthält. Das macht ihn zum richtigen Ort für Bereinigungen — Dateien schließen, Sperren freigeben, eine Transaktion zurückrollen — die auf jedem Ausführungspfad stattfinden müssen:

<?php

function readConfig()
{
  try {
    return "config loaded";
  } finally {
    echo "Cleanup ran." . PHP_EOL;
  }
}

echo readConfig() . PHP_EOL;

Ausgabe:

Cleanup ran.
config loaded

Der finally-Block wird vor der tatsächlichen Rückgabe des Funktionswerts ausgeführt. Vermeiden Sie es, aus finally selbst zurückzukehren: Ein return dort überschreibt den Wert aus try/catch und verwirft stillschweigend jede Exception, die gerade ausgelöst wurde.

Eine Exception weiterwerfen

Ein catch-Block kann teilweise Arbeit erledigen — den Fehler protokollieren, Kontext hinzufügen — und dann weiterwerfen, damit ein übergeordneter Aufrufer entscheiden kann, was zu tun ist. Verwenden Sie throw $e;, um dasselbe Objekt weiterzuwerfen:

<?php

try {
  try {
    throw new Exception("Disk full.");
  } catch (Exception $e) {
    echo "Logging: " . $e->getMessage() . PHP_EOL;
    throw $e; // hand it to the outer handler
  }
} catch (Exception $e) {
  echo "Outer handler: " . $e->getMessage() . PHP_EOL;
}

Ausgabe:

Logging: Disk full.
Outer handler: Disk full.

Häufige Fallstricke

  • try braucht einen Partner. Ein try-Block allein lässt sich nicht parsen — kombinieren Sie ihn mit mindestens einem catch oder einem finally.
  • Nicht alle Fehler sind Exceptions. Viele Laufzeitwarnungen (eine undefinierte Variable, ein fehlgeschlagenes fopen()) werden nicht als Exceptions ausgelöst, daher wird catch sie nicht sehen. Verwenden Sie für diese set_error_handler() oder prüfen Sie Rückgabewerte. Fatale Error-Objekte (wie TypeError) können abgefangen werden, da sie Throwable implementieren.
  • Ordnen Sie catch-Blöcke vom Spezifischen zum Allgemeinen. Ein breites catch (Exception $e) an erster Stelle verbirgt jeden nachfolgenden Block.
  • Nicht stillschweigend schlucken. Ein leerer catch-Block verbirgt den Fehler; protokollieren Sie mindestens $e->getMessage(), damit das Problem sichtbar ist.
  • finally kann Exceptions verbergen. Eine Rückgabe aus finally verwirft sowohl den try-Rückgabewert als auch jede laufende Exception.

Wann sollte ich try verwenden?

Greifen Sie zu try/catch, wenn ein Fehler außergewöhnlich ist und der aufrufende Code vernünftigerweise darauf reagieren kann: eine Datenbankverbindung, die abbricht, eine API, die einen Fehler zurückgibt, ungültige Benutzereingaben, die Sie sauber ablehnen möchten. Für den normalen Kontrollfluss (wurde ein Schlüssel in einem Array gefunden? ist ein string leer?), verwenden Sie normale Bedingungen — Exceptions sind für den abnormalen Pfad, nicht für alltägliche Verzweigungen.

Verwandte Themen

Übung

Übung
Welches Tag wird in PHP verwendet, um einen Codeblock zu starten?
Welches Tag wird in PHP verwendet, um einen Codeblock zu starten?
Was this page helpful?