PHP Error Handling
PHPError handling is essential for building robust PHP applications. PHP provides several mechanisms — from basic error reporting to try/catch exceptions — to handle things that go wrong gracefully.
Types of Errors in PHP
| Type | Description | Fatal? |
|---|---|---|
| Notice | Minor issue (undefined variable) | No |
| Warning | Something wrong but continues | No |
| Fatal Error | Stops execution immediately | Yes |
| Parse Error | Syntax error in code | Yes |
| Exception | Thrown manually, catchable | No (if caught) |
Basic Error Reporting
PHP
<?php
// Show ALL errors (development only!)
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Hide errors (production)
error_reporting(0);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', '/var/log/php_errors.log');
?>try / catch / finally
PHP
<?php
try {
// Code that might fail
$result = 10 / 0;
throw new Exception("Something went wrong!");
} catch (Exception $e) {
// Handle the error
echo "Error: " . $e->getMessage();
echo "File: " . $e->getFile();
echo "Line: " . $e->getLine();
} finally {
// Always runs — whether error or not
echo "This always runs!";
}
?>Multiple catch blocks
PHP
<?php
function connectDB(string $host): PDO {
try {
return new PDO("mysql:host=$host;dbname=test", 'user', 'pass');
} catch (PDOException $e) {
throw new RuntimeException("DB connection failed: " . $e->getMessage());
}
}
try {
$pdo = connectDB('localhost');
$stmt = $pdo->query("SELECT * FROM users");
} catch (PDOException $e) {
echo "Database error: " . $e->getMessage();
} catch (RuntimeException $e) {
echo "Runtime error: " . $e->getMessage();
} catch (Exception $e) {
// Catch anything else
echo "General error: " . $e->getMessage();
} finally {
echo "Cleanup code here";
}
?>Custom Exception Classes
PHP
<?php
// Define custom exceptions
class ValidationException extends Exception {
private array $errors;
public function __construct(array $errors) {
$this->errors = $errors;
parent::__construct("Validation failed");
}
public function getErrors(): array {
return $this->errors;
}
}
class NotFoundException extends Exception {
public function __construct(string $resource, int $id) {
parent::__construct("$resource with ID $id not found", 404);
}
}
// Using custom exceptions
function findUser(int $id): array {
$user = getUserFromDB($id);
if (!$user) {
throw new NotFoundException('User', $id);
}
return $user;
}
function createUser(array $data): void {
$errors = [];
if (empty($data['name'])) $errors[] = 'Name is required';
if (empty($data['email'])) $errors[] = 'Email is required';
if (!empty($errors)) {
throw new ValidationException($errors);
}
// save user...
}
try {
createUser(['name' => '']);
} catch (ValidationException $e) {
foreach ($e->getErrors() as $error) {
echo "• $error
";
}
} catch (NotFoundException $e) {
echo $e->getMessage(); // User with ID 5 not found
http_response_code($e->getCode()); // 404
}
?>Global Exception Handler
PHP
<?php
// Catch ALL unhandled exceptions
set_exception_handler(function (Throwable $e) {
error_log($e->getMessage() . " in " . $e->getFile() . ":" . $e->getLine());
// Show friendly error page instead of crash
http_response_code(500);
echo "<h1>Something went wrong</h1>";
echo "<p>We're working on it. Please try again later.</p>";
});
// Catch ALL errors (PHP 7+)
set_error_handler(function ($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
?>Real-World Example — File Upload
PHP
<?php
function uploadFile(array $file, string $destination): string {
// Validate file exists
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new RuntimeException("Upload failed with error code: " . $file['error']);
}
// Validate file type
$allowed = ['image/jpeg', 'image/png', 'image/gif'];
if (!in_array($file['type'], $allowed)) {
throw new InvalidArgumentException("Invalid file type: " . $file['type']);
}
// Validate file size (max 2MB)
if ($file['size'] > 2 * 1024 * 1024) {
throw new OverflowException("File too large: " . $file['size'] . " bytes");
}
// Move file
$filename = uniqid() . '_' . basename($file['name']);
$path = $destination . '/' . $filename;
if (!move_uploaded_file($file['tmp_name'], $path)) {
throw new RuntimeException("Failed to move uploaded file");
}
return $filename;
}
try {
$filename = uploadFile($_FILES['photo'], '/uploads');
echo "Uploaded: $filename";
} catch (InvalidArgumentException $e) {
echo "Invalid file: " . $e->getMessage();
} catch (OverflowException $e) {
echo "File too large: " . $e->getMessage();
} catch (RuntimeException $e) {
echo "Upload error: " . $e->getMessage();
}
?>💡
Never show raw errors in production! Always log errors server-side and show a friendly message to users. Raw PHP errors expose your code structure to attackers.
💡
In Laravel, exceptions are handled automatically! The
app/Exceptions/Handler.php file catches all exceptions and returns appropriate responses. You rarely need manual try/catch in controllers.Test your knowledge!
Take a quiz to reinforce what you learned.