The role of register_shutdown_function is to register a callback function at the end of the PHP script execution, which is called when the script terminates. It is often used to log fatal errors, release resources, or do some post-processing work.
register_shutdown_function(function () {
$error = error_get_last();
if ($error !== null) {
// Error handling logic
file_put_contents('/tmp/php_error.log', print_r($error, true));
}
});
The error that register_shutdown_function can catch is usually a "fatal error" recorded in error_get_last() before the script terminates. Common types of errors that can be caught include:
E_ERROR : Fatal error at runtime
E_PARSE : parsing error (in some cases)
E_CORE_ERROR , E_COMPILE_ERROR : Fatal error when PHP starts
E_USER_ERROR : A fatal error defined by user
These errors usually cause script interrupts, in which case the shutdown function has a chance to run and capture error details via error_get_last() .
Although register_shutdown_function is powerful, it is not omnipotent. The following types of errors or situations are uncaught:
Non-fatal errors do not cause script interrupts, so error handling logic in register_shutdown_function is not triggered:
echo $undefined_variable; // Report notice,Does not affect execution
Although the shutdown function will be called, the content returned by error_get_last() will not contain these non-fatal errors.
If the script exits actively via exit or die and does not throw a fatal error before exiting, then the return value of error_get_last() is null :
exit("Exit the program"); // trigger shutdown,But no error records
Some syntax errors occur during the PHP parsing phase, and the script does not even enter the execution process, which means register_shutdown_function has no chance to register:
// The following code directly causes parsing to fail,Unable to register shutdown function
echo "Hello
Although it is not "Error cannot be caught", it should be noted that if ob_start() is not enabled before a fatal error occurs, the output of the page may be lost, resulting in no error prompts. This situation is often mistaken for "the shutdown function is invalid".
The error suppressor will not prevent fatal errors, but will suppress the display of non-fatal errors, which can easily cause confusion. register_shutdown_function can catch fatal errors even with @ :
@trigger_error("This is a user warning", E_USER_WARNING); // Will not be captured
As mentioned earlier, register_shutdown_function can only handle fatal errors and cannot be used as a general error handling mechanism. For E_WARNING and E_NOTICE , set_error_handler should be used.
Error handling should be defended at multiple levels. Best practice is to use it in combination:
set_error_handler() captures non-fatal errors such as warnings and notifications;
set_exception_handler() catches uncaught exceptions;
register_shutdown_function() captures the last error before the script terminates.
Many times, shutdown is indeed executed, but because error_get_last() returns null and nothing is recorded, the developer mistakenly thinks that the function does not work.
For a more comprehensive error handling system, the following combination is recommended:
set_error_handler('customErrorHandler');
set_exception_handler('customExceptionHandler');
register_shutdown_function('shutdownHandler');
function customErrorHandler($errno, $errstr, $errfile, $errline) {
// Record warning、notice wait
}
function customExceptionHandler($exception) {
// Record未捕获异常
}
function shutdownHandler() {
$error = error_get_last();
if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
// 致命错误Record
file_get_contents('https://gitbox.net/log.php?msg=' . urlencode($error['message']));
}
}