Wenn Sie ein neues Laravel-Projekt anlegen, sind Fehler- und Ausnahmebehandlung bereits vorkonfiguriert.
Anpassungen nehmen Sie über die Methode withExceptions in bootstrap/app.php vor.
Vom Auslösen einer Ausnahme bis zur Antwort an den Client durchläuft Laravel folgende Schritte:
// bootstrap/app.phpuse Illuminate\Foundation\Application;use Illuminate\Foundation\Configuration\Exceptions;return Application::configure(basePath: dirname(__DIR__)) ->withExceptions(function (Exceptions $exceptions): void { // Reporting und Rendering von Ausnahmen hier konfigurieren })->create();
Das an die withExceptions-Closure übergebene Objekt $exceptions ist eine Instanz von Illuminate\Foundation\Configuration\Exceptions und verwaltet die gesamte Ausnahmebehandlung Ihrer Anwendung.
Die Option debug in config/app.php steuert, wie viele Fehlerinformationen ausgegeben werden.
Standardmäßig übernimmt sie den Wert der Umgebungsvariable APP_DEBUG aus der .env-Datei.
# Lokale EntwicklungAPP_DEBUG=true# ProduktionAPP_DEBUG=false
Setzen Sie APP_DEBUG in der Produktion unbedingt auf false. Andernfalls können sensible Informationen an Endnutzer gelangen.
Beim Reporting wird eine Ausnahme protokolliert oder an externe Dienste wie Sentry oder Flare gesendet.
Standardmäßig wird gemäß den Einstellungen in config/logging.php in ein Log geschrieben.
Möchten Sie je nach Ausnahmetyp unterschiedliche Report-Logik ausführen, übergeben Sie eine Closure an die Methode report.
Laravel erkennt den Ausnahmetyp anhand der Type-Hints der Closure.
use App\Exceptions\InvalidOrderException;->withExceptions(function (Exceptions $exceptions): void { $exceptions->report(function (InvalidOrderException $e) { // Benachrichtigung an externen Dienst usw. });})
Auch wenn Sie eine eigene Callback registrieren, wird das Standard-Logging weiter ausgeführt.
Um die Standard-Propagation abzubrechen, rufen Sie stop() auf oder geben Sie false zurück.
Wird dieselbe Ausnahme-Instanz mehrfach an report() übergeben, entstehen doppelte Log-Einträge.
Mit dontReportDuplicates() protokolliert Laravel dieselbe Instanz nur beim ersten Mal.
Um allen Log-Einträgen zu Ausnahmen dieselben Informationen anzuhängen, verwenden Sie context.
Die aktuell angemeldete Benutzer-ID wird, sofern verfügbar, automatisch mitgegeben.
Beim Rendering wird eine Ausnahme in eine HTTP-Antwort umgewandelt.
Standardmäßig erzeugt Laravel eine passende Antwort automatisch; Anpassungen sind aber möglich.
Auch das Rendering integrierter Ausnahmen (etwa NotFoundHttpException) lässt sich überschreiben.
Liefert die Closure keinen Wert, wird das Standardrendering verwendet.
Sie können in app/Exceptions/ eigene Ausnahmeklassen anlegen.
Definieren Sie in der Klasse Methoden report() und render(), werden sie automatisch aufgerufen – auch ohne Konfiguration in bootstrap/app.php.
// Wenn $condition true ist, abbrechenabort_if(! $user->isAdmin(), 403);// Wenn $condition false ist, abbrechenabort_unless($user->hasPermission('edit'), 403, 'Permission denied.');
Praktisch bei Berechtigungsprüfungen in Controllern oder Middleware, häufig in Kombination mit Gates und Policies.
Als Fallback für Statuscodes ohne eigene View können Sie 4xx.blade.php und 5xx.blade.php anlegen.
resources/└── views/ └── errors/ ├── 4xx.blade.php # Fallback für 4xx └── 5xx.blade.php # Fallback für 5xx
Für 404, 500 und 503 liefert Laravel bereits eigene Standardseiten. Wenn Sie diese anpassen möchten, legen Sie statt eines Fallbacks eigene Dateien (404.blade.php usw.) an.
Eine gemeinsame Basisklasse für API-Ausnahmen ermöglicht konsistente Fehlerantworten aus jedem Endpunkt.
<?phpnamespace App\Exceptions;use Exception;use Illuminate\Http\JsonResponse;use Illuminate\Http\Request;class ApiException extends Exception{ public function __construct( string $message = 'An error occurred.', private readonly int $statusCode = 500, private readonly array $errors = [], ) { parent::__construct($message); } public function render(Request $request): JsonResponse { $data = ['message' => $this->getMessage()]; if (! empty($this->errors)) { $data['errors'] = $this->errors; } return response()->json($data, $this->statusCode); }}
Verwendung im Controller:
<?phpnamespace App\Http\Controllers\Api;use App\Exceptions\ApiException;use App\Models\Order;class OrderController extends Controller{ public function show(int $id): JsonResponse { $order = Order::find($id); if (! $order) { throw new ApiException('Bestellung nicht gefunden.', 404); } if ($order->isCancelled()) { throw new ApiException('Diese Bestellung wurde bereits storniert.', 422); } return response()->json($order); }}