PHP Error Handling
PHP Error and Exception Handling
Section titled “PHP Error and Exception Handling”Effective error handling is crucial for building robust and secure PHP applications. It involves detecting errors, reporting them appropriately (logging for developers, user-friendly messages for users), and potentially recovering from them.
Types of Errors in PHP
Section titled “Types of Errors in PHP”PHP distinguishes between several types of issues:
- Notices: Non-critical issues found during script execution (e.g., using an undefined variable). Execution usually continues.
- Warnings: More serious non-fatal errors (e.g., including a non-existent file). Execution usually continues.
- Fatal Errors: Critical errors that halt script execution (e.g., calling an undefined function, parse errors). In PHP 7+, many of these now throw
Errorexceptions. - Exceptions: Object-oriented way to handle runtime errors or exceptional conditions (
ExceptionandErrorclasses implementingThrowable). Covered in the Exceptions chapter.
Modern PHP relies heavily on the Exception model (try...catch...finally) for handling runtime problems, including many errors that were previously fatal.
Basic Error Handling: The die() or exit() Construct
Section titled “Basic Error Handling: The die() or exit() Construct”A very simple, but often crude, way to handle a fatal condition is to stop script execution using die() or exit() (they are aliases).
Example: Checking file existence before opening:
<?php$filename = "nonexistent_file.txt";
if (!file_exists($filename)) { // Stop script execution and output a message die("Error: File '{$filename}' not found. Cannot proceed.");}
// This code will only run if the file existsecho "File exists, proceeding...";$fileHandle = fopen($filename, "r");// ... process file ...?>While die() prevents further execution after a critical error, it provides a poor user experience and bypasses any cleanup logic (like closing database connections). It’s generally discouraged in favor of exceptions or more graceful error handling in production applications.
Configuring Error Reporting
Section titled “Configuring Error Reporting”PHP’s error reporting behavior is controlled by settings in the php.ini configuration file or dynamically within scripts using functions like error_reporting() and ini_set().
Key Directives (php.ini):
error_reporting(e.g.,E_ALL): Sets the level of errors that PHP should report.E_ALLis recommended during development to catch all issues (notices, warnings, etc.).display_errors(e.g.,OnorOff): Determines whether errors should be displayed directly in the browser output. Should beOnduring development but strictlyOffin production to avoid exposing sensitive information.log_errors(e.g.,OnorOff): Determines whether errors should be written to a log file. Should beOnin production.error_log(e.g.,/var/log/php_errors.logorsyslog): Specifies the file or system logger where errors should be logged whenlog_errorsisOn.
Development vs. Production Settings:
- Development:
error_reporting = E_ALL,display_errors = On,log_errors = On(optional, but good). - Production:
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT(or similar, report most things except notices/deprecations if desired),display_errors = Off,log_errors = On,error_log = /path/to/secure/log/file.
You can override php.ini settings temporarily in a script:
<?php// Recommended for development: Show all errorsini_set('display_errors', '1');ini_set('display_startup_errors', '1');error_reporting(E_ALL);
// Example of triggering a noticeecho $undefinedVariable;
// Code that might cause a warninginclude 'non_existent_file.php';?>Custom Error Handler (set_error_handler)
Section titled “Custom Error Handler (set_error_handler)”For non-exception errors (primarily notices and warnings), you can define a custom function to handle them using set_error_handler(). This allows you to intercept these errors and decide how to log or display them.
This is less commonly needed now that many fatal errors throw Error exceptions, but it can still be useful for logging notices/warnings during development or converting specific warnings into exceptions.
The handler function receives parameters like error level, message, file, line number, and context.
Syntax: set_error_handler(callable $callback, int $error_levels = E_ALL | E_STRICT)
Example: Logging warnings and notices:
<?phpdeclare(strict_types=1);
// Custom error handler functionfunction customErrorHandler(int $errno, string $errstr, string $errfile, int $errline): bool{ // Log the error (adjust path and format as needed) $logMessage = "[" . date("Y-m-d H:i:s") . "] Error [$errno]: $errstr in $errfile on line $errline\n"; error_log($logMessage, 3, "/path/to/your/app_errors.log");
// To prevent PHP's internal handler from running, return true. // If you return false or nothing, PHP's standard error handling will proceed. // Don't display errors directly in production! if (ini_get('display_errors')) { // Only display if configured echo "**Error Caught:** [$errno] $errstr in $errfile:$errline<br>"; }
// Let PHP continue if it's just a notice/warning, but halt for user errors maybe? // This logic depends on your needs. /* switch ($errno) { case E_USER_ERROR: echo "Fatal error caught. Halting."; exit(1); break; case E_USER_WARNING: case E_USER_NOTICE: // Logged above, continue execution break; default: // Standard PHP notice/warning, logged above, continue execution break; } */
return true; // Suppress PHP's default handler for handled types}
// Set the custom handler to catch all errors (including notices, warnings)set_error_handler('customErrorHandler', E_ALL);
// Trigger a noticeecho $someUndefinedVar;
// Trigger a warninginclude 'non_existent_script.php';
echo "Script execution might continue depending on handler logic...";?>Note: The custom error handler set by set_error_handler() cannot handle fatal errors like parse errors or most errors that now throw Error exceptions in PHP 7+. Use register_shutdown_function() for some fatal error detection or try...catch (Throwable $t) for exceptions/errors.
Triggering Custom Errors (trigger_error)
Section titled “Triggering Custom Errors (trigger_error)”You can generate user-level errors (notices, warnings, or fatal errors) from within your code using the trigger_error() function. This is useful for indicating problems in your application logic or library usage.
Syntax: trigger_error(string $message, int $error_type = E_USER_NOTICE)
Error Types:
E_USER_NOTICE(Default): Like a standard PHP notice.E_USER_WARNING: Like a standard PHP warning.E_USER_ERROR: Like a fatal PHP error (halts execution unless handled by a custom error handler that exits).E_USER_DEPRECATED: Indicate deprecated functionality.
Example:
<?phpfunction calculateDivision(float $numerator, float $denominator): float { if ($denominator == 0) { // Trigger a user warning for invalid input trigger_error("Division by zero attempted", E_USER_WARNING); return NAN; // Not a Number } if ($numerator < 0) { // Example: Trigger a notice if numerator is negative trigger_error("Numerator is negative, proceeding anyway.", E_USER_NOTICE); } return $numerator / $denominator;}
// Set a simple error handler to see the triggered errorsset_error_handler(function($errno, $errstr){ echo "Triggered Error: $errstr\n";}, E_USER_NOTICE | E_USER_WARNING);
$result1 = calculateDivision(10, 0);echo "Result 1: $result1\n";
$result2 = calculateDivision(-5, 2);echo "Result 2: $result2\n";?>Output:
Triggered Error: Division by zero attemptedResult 1: NANTriggered Error: Numerator is negative, proceeding anyway.Result 2: -2.5Error Logging (error_log)
Section titled “Error Logging (error_log)”The error_log() function allows you to explicitly send messages to PHP’s configured error log mechanism (file, syslog) or even via email (though email logging is generally discouraged for high volume).
This is useful for logging specific application events or detailed debug information separate from standard PHP errors.
Syntax: error_log(string $message, int $message_type = 0, ?string $destination = null, ?string $additional_headers = null): bool
Common message_type values:
0(Default): Send message to PHP’s system logger (useserror_logdirective inphp.ini).1: Send message via email to the address specified in thedestinationparameter.3: Append message to the file specified indestination.
Example: Logging a custom message to the standard PHP error log:
<?php$userId = 123;$action = "update_profile";
// ... some logic ...
if (/* some condition indicating success */ true) { $logMsg = "User ID {$userId} successfully performed action '{$action}'."; error_log($logMsg); // Sends to the configured PHP error log (type 0) echo "Action logged.";} else { $logMsg = "User ID {$userId} failed action '{$action}'."; error_log($logMsg); // Log failure too echo "Action failure logged.";}?>Example: Logging to a specific file (ensure permissions are correct):
<?php$customLogFile = '/var/log/my_app_debug.log'; // Make sure this file is writable by the web server$debugInfo = "Processing started for request ID: " . uniqid();
error_log(date('[Y-m-d H:i:s] ') . $debugInfo . "\n", 3, $customLogFile);echo "Debug info written to custom log.";?>Caution: Avoid logging sensitive data like passwords or personal information.