← Tilbage til koncepter
Error & Exception Handling
Try-catch blocks, custom exceptions, error handlers og Throwable hierarchy i moderne PHP
Kategori: Fundamentals
🎯 Key Points
- ✓try-catch-finally - Struktureret exception handling med cleanup i finally block
- ✓Throwable interface - Root interface for både Exception og Error classes (PHP 7+)
- ✓Exception hierarchy - Custom exceptions der extender base Exception class
- ✓Error class - Catchable errors som TypeError, DivisionByZeroError (PHP 7+)
- ✓Custom exceptions - Domain-specific exception classes med custom properties og methods
- ✓set_exception_handler() - Global exception handler for uncaught exceptions
- ✓set_error_handler() - Convert PHP errors (warnings, notices) til exceptions
- ✓finally block - Kode der altid eksekveres uanset om exception blev kastet
- ✓throw keyword - Kast exceptions for at signalere error conditions
- ✓Multiple catch blocks - Catch forskellige exception types med forskellig handling
- ✓Exception chaining - Previous exception parameter for nested error context
- ✓SPL exceptions - Built-in exception types som InvalidArgumentException, RuntimeException
💻 Kode Eksempel
<?php
// Custom exception hierarchy
class DatabaseException extends Exception {}
class ConnectionException extends DatabaseException {}
class QueryException extends DatabaseException {
public function __construct(
string $message,
private string $query,
int $code = 0,
?Throwable $previous = null
) {
parent::__construct($message, $code, $previous);
}
public function getQuery(): string {
return $this->query;
}
}
// Database class with proper error handling
class Database {
private ?PDO $connection = null;
public function connect(string $dsn): void {
try {
$this->connection = new PDO($dsn);
$this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
throw new ConnectionException(
"Failed to connect to database: {$e->getMessage()}",
(int)$e->getCode(),
$e
);
}
}
public function query(string $sql): array {
if (!$this->connection) {
throw new ConnectionException('Not connected to database');
}
try {
$stmt = $this->connection->query($sql);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
throw new QueryException(
"Query failed: {$e->getMessage()}",
$sql,
(int)$e->getCode(),
$e
);
}
}
}
// Usage with multiple catch blocks
try {
$db = new Database();
$db->connect('sqlite::memory:');
// This will fail - invalid SQL
$results = $db->query('INVALID SQL');
} catch (ConnectionException $e) {
echo "Connection error: {$e->getMessage()}\n";
// Handle connection errors specifically
} catch (QueryException $e) {
echo "Query error: {$e->getMessage()}\n";
echo "Failed query: {$e->getQuery()}\n";
// Check if there's a previous exception
if ($prev = $e->getPrevious()) {
echo "Caused by: {$prev->getMessage()}\n";
}
} catch (DatabaseException $e) {
echo "General database error: {$e->getMessage()}\n";
} finally {
echo "Cleanup completed\n";
}
// Custom error handler to convert errors to exceptions
set_error_handler(function($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
try {
// This warning will become an exception
$result = 10 / 0; // Division by zero warning
} catch (ErrorException $e) {
echo "Caught error as exception: {$e->getMessage()}\n";
}
restore_error_handler();💼 Hvornår bruges det?
- •API error responses hvor exceptions mappes til HTTP status codes og JSON error payloads
- •Database operations hvor connection failures, query errors og transaction rollbacks håndteres
- •File operations hvor missing files, permission errors og disk full scenarios catches gracefully
- •External API calls hvor network timeouts, invalid responses og rate limits triggerer exceptions
- •Form validation hvor ValidationException samler alle validation errors til user feedback
- •Payment processing hvor PaymentException håndterer declined cards, insufficient funds og gateway errors
⭐ Best Practices
- ✓Create custom exception hierarchies for domain-specific errors - gør det lettere at catch specifikt
- ✓Always catch most specific exceptions first - rækkefølge matters i multiple catch blocks
- ✓Use finally blocks for cleanup operations (close files, connections) der skal ske uanset hvad
- ✓Log exceptions med context - message, stack trace, request data for debugging production issues
- ✓Never catch Throwable unless du re-throws - catching alt kan skjule critical errors
- ✓Include previous exception i custom exceptions for full error chain og debugging context
- ✓Throw exceptions for exceptional conditions only - ikke til normal control flow
- ✓Use SPL exceptions når muligt - InvalidArgumentException, RuntimeException etc frem for generic Exception
ℹ️ Quick Info
Kategori
Fundamentals
Sværhedsgrad
Mellem