Hallo Welt
Hallo Welt
Original Lingva Deutsch
Übersetzung wird vorbereitet...
Dieser Vorgang kann bis zu 60 Sekunden dauern.
Diese Seite wird erstmalig übersetzt und dann für alle Besucher gespeichert.
0%
DE Zurück zu Deutsch
Übersetzung durch Lingva Translate

234 Dokumentationen verfügbar

Wissensdatenbank

PHP Error Handling Exceptions

Zuletzt aktualisiert: 20.01.2026 um 10:05 Uhr

PHP Error Handling: Exceptions richtig nutzen

Gutes Error Handling macht den Unterschied zwischen robuster Software und Chaos. Lernen Sie, wie Sie Exceptions in PHP richtig einsetzen.

Exception Grundlagen

Exception werfen

<?php
function divide(int $a, int $b): float
{
    if ($b === 0) {
        throw new InvalidArgumentException('Division durch Null nicht erlaubt');
    }
    return $a / $b;
}

Exception fangen

<?php
try {
    $result = divide(10, 0);
    echo "Ergebnis: $result";
} catch (InvalidArgumentException $e) {
    echo "Fehler: " . $e->getMessage();
} catch (Exception $e) {
    echo "Unerwarteter Fehler: " . $e->getMessage();
} finally {
    // Wird IMMER ausgeführt
    echo "Fertig!";
}

Exception-Hierarchie

Throwable (Interface)
├── Error (PHP-interne Fehler)
│   ├── TypeError
│   ├── ArgumentCountError
│   └── ...
└── Exception (Anwendungs-Exceptions)
    ├── LogicException
    │   ├── InvalidArgumentException
    │   ├── OutOfRangeException
    │   └── ...
    └── RuntimeException
        ├── OutOfBoundsException
        ├── UnexpectedValueException
        └── ...

Eigene Exception-Klassen

<?php
namespace App\Exception;

class ValidationException extends \Exception
{
    private array $errors;

    public function __construct(array $errors, string $message = 'Validierung fehlgeschlagen')
    {
        parent::__construct($message);
        $this->errors = $errors;
    }

    public function getErrors(): array
    {
        return $this->errors;
    }
}

class UserNotFoundException extends \RuntimeException
{
    public function __construct(int $userId)
    {
        parent::__construct("User mit ID $userId nicht gefunden");
    }
}

class DatabaseException extends \RuntimeException {}
class AuthenticationException extends \RuntimeException {}

Verwendung

<?php
use App\Exception\ValidationException;
use App\Exception\UserNotFoundException;

function createUser(array $data): User
{
    $errors = [];

    if (empty($data['email'])) {
        $errors['email'] = 'E-Mail ist erforderlich';
    }

    if (empty($data['password'])) {
        $errors['password'] = 'Passwort ist erforderlich';
    }

    if (!empty($errors)) {
        throw new ValidationException($errors);
    }

    return new User($data);
}

try {
    $user = createUser($_POST);
} catch (ValidationException $e) {
    $errors = $e->getErrors();
    // Fehler an Template übergeben
}

Exception mit Kontext

<?php
try {
    $user = $repository->find($id);
} catch (DatabaseException $e) {
    // Ursprüngliche Exception als "Previous" weitergeben
    throw new UserNotFoundException($id, $e);
}

// Exception-Kette auslesen
catch (UserNotFoundException $e) {
    echo $e->getMessage();
    echo $e->getPrevious()?->getMessage(); // Ursprünglicher Fehler
}

Error Handler für nicht gefangene Exceptions

<?php
set_exception_handler(function (Throwable $e): void {
    error_log($e->getMessage() . "\n" . $e->getTraceAsString());

    if (getenv('APP_DEBUG') === 'true') {
        echo "<pre>";
        echo "Error: " . $e->getMessage() . "\n";
        echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
        echo $e->getTraceAsString();
        echo "</pre>";
    } else {
        http_response_code(500);
        echo "Ein Fehler ist aufgetreten.";
    }
});

PHP Errors zu Exceptions konvertieren

<?php
set_error_handler(function (
    int $severity,
    string $message,
    string $file,
    int $line
): bool {
    // Error als Exception werfen
    throw new ErrorException($message, 0, $severity, $file, $line);
});

// Jetzt werden auch Warnings zu Exceptions
try {
    $content = file_get_contents('nicht-vorhanden.txt');
} catch (ErrorException $e) {
    echo "Datei konnte nicht gelesen werden";
}

API Error Response

<?php
class ApiController
{
    public function handle(): void
    {
        try {
            $result = $this->processRequest();
            $this->jsonResponse($result);

        } catch (ValidationException $e) {
            $this->jsonError(422, 'Validierungsfehler', $e->getErrors());

        } catch (AuthenticationException $e) {
            $this->jsonError(401, 'Nicht authentifiziert');

        } catch (UserNotFoundException $e) {
            $this->jsonError(404, $e->getMessage());

        } catch (Throwable $e) {
            error_log($e->getMessage());
            $this->jsonError(500, 'Interner Serverfehler');
        }
    }

    private function jsonError(int $status, string $message, array $details = []): void
    {
        http_response_code($status);
        header('Content-Type: application/json');
        echo json_encode([
            'error' => true,
            'message' => $message,
            'details' => $details ?: null
        ]);
    }
}

Best Practices

💡 Empfehlungen:
  • Spezifische Exceptions werfen, nicht nur Exception
  • Exceptions früh werfen, spät fangen
  • Kontext in Exception-Message geben
  • Nie leere catch-Blöcke (mindestens loggen)
  • In Produktion: keine Stack-Traces anzeigen
  • Exception für außergewöhnliche Fälle, nicht für Kontrollfluss

Was NICHT tun

❌ Anti-Patterns:
// ❌ Leerer catch-Block
try {
    riskyOperation();
} catch (Exception $e) {
    // Fehler ignorieren - SCHLECHT!
}

// ❌ Pokemon Exception Handling
try {
    everything();
} catch (Exception $e) {
    // Gotta catch 'em all - aber was tun damit?
}

// ❌ Exception für Kontrollfluss
try {
    $user = findUser($id);
} catch (UserNotFoundException $e) {
    // Besser: if ($user === null)
}

Weitere Informationen