PHP Fundamentals
Error Types & Error Handling
Error Types & Error Handling
Understanding and properly handling errors is crucial for building robust PHP applications. PHP provides several error types and mechanisms to help you identify and resolve issues in your code.
PHP Error Types
PHP has several error levels that indicate the severity of different issues:
<?php
// 1. Parse Errors (E_PARSE) - Fatal syntax errors
// echo "Hello World // Missing closing quote - script won't run
// 2. Fatal Errors (E_ERROR) - Critical errors that stop execution
// callNonExistentFunction(); // Fatal error
// 3. Warning Errors (E_WARNING) - Non-fatal errors, script continues
$file = fopen("nonexistent.txt", "r"); // Warning: file not found
// 4. Notice Errors (E_NOTICE) - Minor issues, script continues
echo $undefinedVariable; // Notice: undefined variable
// 5. Deprecated Errors (E_DEPRECATED) - Features that will be removed
// Using old PHP features generates these warnings
// 6. Strict Errors (E_STRICT) - Code improvement suggestions
// Suggestions for better code practices
?>
Note: Fatal errors and parse errors will stop script execution immediately, while warnings and notices allow the script to continue running.
Error Reporting Configuration
You can control which errors are reported and how they are displayed:
<?php
// Display all errors (for development)
error_reporting(E_ALL);
ini_set('display_errors', 1);
// Display all errors except notices
error_reporting(E_ALL & ~E_NOTICE);
// Turn off error display (for production)
error_reporting(0);
ini_set('display_errors', 0);
// Log errors to a file instead of displaying
ini_set('log_errors', 1);
ini_set('error_log', '/path/to/error.log');
// Common production configuration
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
?>
Warning: Never display errors in production! Always log them to a file and show user-friendly messages instead.
Custom Error Handlers
You can create custom error handlers to control how errors are processed:
<?php
// Define a custom error handler
function customErrorHandler($errno, $errstr, $errfile, $errline) {
$errorTypes = [
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_NOTICE => 'Notice',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice'
];
$type = $errorTypes[$errno] ?? 'Unknown Error';
// Log the error
$message = "[$type] $errstr in $errfile on line $errline";
error_log($message);
// Display user-friendly message
echo "<div class='error'>An error occurred. Please try again later.</div>";
// For critical errors, stop execution
if ($errno === E_ERROR || $errno === E_USER_ERROR) {
die("Critical error - script terminated");
}
return true; // Prevent PHP's default error handler
}
// Register the custom error handler
set_error_handler('customErrorHandler');
// Trigger different error types
trigger_error("This is a user notice", E_USER_NOTICE);
trigger_error("This is a user warning", E_USER_WARNING);
?>
Triggering Custom Errors
You can trigger your own errors using the trigger_error() function:
<?php
function divideNumbers($dividend, $divisor) {
if ($divisor == 0) {
trigger_error("Division by zero attempted", E_USER_WARNING);
return false;
}
return $dividend / $divisor;
}
$result = divideNumbers(10, 0);
if ($result === false) {
echo "Operation failed";
}
?>
Error Suppression Operator
The @ operator suppresses error messages, but use it cautiously:
<?php
// Without suppression - shows warning
$content = file_get_contents('nonexistent.txt');
// With suppression - no warning displayed
$content = @file_get_contents('nonexistent.txt');
// Better approach: check the result
$content = @file_get_contents('nonexistent.txt');
if ($content === false) {
echo "File could not be read";
}
?>
Tip: Instead of suppressing errors with @, it's better to check return values and handle errors explicitly.
Shutdown Function
Register a function to run when the script terminates, useful for catching fatal errors:
<?php
function shutdownHandler() {
$error = error_get_last();
if ($error !== null && $error['type'] === E_ERROR) {
// Log fatal error
error_log("Fatal error: " . $error['message']);
// Display user-friendly message
echo "<h1>Oops! Something went wrong</h1>";
echo "<p>We're working on fixing this issue.</p>";
}
}
register_shutdown_function('shutdownHandler');
// Your application code here
?>
Best Practices for Error Handling
<?php
// 1. Development environment
if ($_SERVER['SERVER_NAME'] === 'localhost') {
error_reporting(E_ALL);
ini_set('display_errors', 1);
} else {
// 2. Production environment
error_reporting(E_ALL);
ini_set('display_errors', 0);
ini_set('log_errors', 1);
ini_set('error_log', __DIR__ . '/logs/errors.log');
}
// 3. Always validate user input
function processAge($age) {
if (!is_numeric($age)) {
trigger_error("Age must be a number", E_USER_WARNING);
return false;
}
if ($age < 0 || $age > 150) {
trigger_error("Age is out of valid range", E_USER_WARNING);
return false;
}
return true;
}
// 4. Check function return values
$file = fopen("data.txt", "r");
if ($file === false) {
error_log("Failed to open data.txt");
die("Unable to access required file");
}
// 5. Use meaningful error messages
trigger_error("Database connection failed: Invalid credentials", E_USER_ERROR);
// Not just: trigger_error("Error", E_USER_ERROR);
?>
Logging Errors to File
<?php
function logError($message, $level = 'ERROR') {
$timestamp = date('Y-m-d H:i:s');
$logMessage = "[$timestamp] [$level] $message" . PHP_EOL;
$logFile = __DIR__ . '/logs/app.log';
// Create logs directory if it doesn't exist
$logDir = dirname($logFile);
if (!is_dir($logDir)) {
mkdir($logDir, 0755, true);
}
// Append to log file
file_put_contents($logFile, $logMessage, FILE_APPEND);
}
// Usage
logError("User authentication failed", 'WARNING');
logError("Database connection lost", 'CRITICAL');
logError("File uploaded successfully", 'INFO');
?>
Exercise:
- Create a custom error handler that logs errors to a file with timestamps
- Write a function that reads a file and handles missing file errors gracefully
- Create a validation function that triggers appropriate errors for invalid email addresses
- Set up different error reporting levels for development and production environments
Common Mistakes to Avoid
<?php
// ❌ Bad: Displaying errors in production
ini_set('display_errors', 1); // Never do this in production!
// ✅ Good: Log errors, don't display them
ini_set('display_errors', 0);
ini_set('log_errors', 1);
// ❌ Bad: Suppressing all errors
@include('config.php');
@$result = $dangerous_operation;
// ✅ Good: Handle errors explicitly
if (file_exists('config.php')) {
include('config.php');
} else {
error_log('Config file missing');
die('Configuration error');
}
// ❌ Bad: Generic error messages
trigger_error("Error", E_USER_ERROR);
// ✅ Good: Descriptive error messages
trigger_error("Failed to connect to database: Connection timeout", E_USER_ERROR);
?>
Production Checklist:
- Turn off error display:
display_errors = 0 - Enable error logging:
log_errors = 1 - Set error log path:
error_log = /path/to/logs - Report all errors:
error_reporting = E_ALL - Use custom error pages for user-facing errors