I\'m taking the leap: my PHP scripts will ALL fail gracefully!
At least, that\'s what I\'m hoping for...`
I don\'t want to wrap (practically) every single line i
Why isn't my custom error handler catching undefinedd functions? Are there other problems that this will cause?
At a guess, I'd say that undefined function errors travel through a different execution path than other error types. Perhaps the PHP designers could tell you more, except I doubt PHP is in any way designed.
If you'd like your scripts to fail gracefully while still writing them PHP-style, try putting the entire page in a function and then call it within a try..catch
block.
I've been playing around with error handling for some time and it seems like it works for the most part.
function fatalHandler() {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerError = error_get_last();
if( $fatalHandlerError !== null ) {
print($fatalHandlerTitle="{$fatalHandlerTitle} | ".join(" | ", $fatalHandlerError).
(preg_match("/memory/i", $fatalHandlerError["message"]) ? " | Mem: limit ".ini_get('memory_limit')." / peak ".round(memory_get_peak_usage(true)/(1024*1024))."M" : "")."\n".
"GET: ".var_export($_GET,1)."\n".
"POST: ".var_export($_POST,1)."\n".
"SESSION: ".var_export($_SESSION,1)."\n".
"HEADERS: ".var_export(getallheaders(),1));
}
return $fatalHandlerTitle;
}
function fatalHandlerInit($title="phpError") {
global $fatalHandlerError, $fatalHandlerTitle;
$fatalHandlerTitle = $title;
$fatalHandlerError = error_get_last();
set_error_handler( "fatalHandler" );
}
Now I have an issue where if the memory is exhausted, it doesn't report it every time. It seems like it depends on how much memory is being used. I did a script to load a large file (takes ~6.6M of memory) in an infinite loop. Setup1:
ini_set('memory_limit', '296M');
fatalHandlerInit("testing");
$file[] = file("large file"); // copy paste a bunch of times
In this case I get the error to be reports and it dies on 45 file load.
Setup2 - same but change: ini_set('memory_limit', '299M');
This time I don't get an error and it doesn't even call my custom error function. The script dies on the same line.
Does anyone have a clue why and how to go around that?
Very interesting thing that I've discovered today as I was facing the similar problem. If you use the following - it will catch the error with your custom error handler function / method:
ini_set('display_errors', 'Off');
error_reporting(-1);
set_error_handler(array("Cmd\Exception\Handler", "getError"), -1 & ~E_NOTICE & ~E_USER_NOTICE);
By setting 'display_errors' to 'Off' you can catch still catch them with the handler.
set_error_handler
is designed to handle errors with codes of: E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE
. This is because set_error_handler
is meant to be a method of reporting errors thrown by the user error function trigger_error
.
However, I did find this comment in the manual that may help you:
"The following error types cannot be handled with a user defined function:
E_ERROR
,E_PARSE
,E_CORE_ERROR
,E_CORE_WARNING
,E_COMPILE_ERROR
,E_COMPILE_WARNING
, and most ofE_STRICT
raised in the file whereset_error_handler()
is called."This is not exactly true.
set_error_handler()
can't handle them, butob_start()
can handle at leastE_ERROR
.<?php function error_handler($output) { $error = error_get_last(); $output = ""; foreach ($error as $info => $string) $output .= "{$info}: {$string}\n"; return $output; } ob_start('error_handler'); will_this_undefined_function_raise_an_error(); ?>
Really though these errors should be silently reported in a file, for example. Hopefully you won't have many E_PARSE
errors in your project! :-)
As for general error reporting, stick with Exceptions (I find it helpful to make them tie in with my MVC system). You can build a pretty versatile Exception to provide options via buttons and add plenty of description to let the user know what's wrong.
I guess you needs to use register_shutdown_function
also
For example:
register_shutdown_function( array( $this, 'customError' ));.
function customError()
{
$arrStrErrorInfo = error_get_last();
print_r( $arrStrErrorInfo );
}
From the documentation (emphasis added):
The following error types cannot be handled with a user defined function: E_ERROR, E_PARSE, E_CORE_ERROR, E_CORE_WARNING, E_COMPILE_ERROR, E_COMPILE_WARNING, and most of E_STRICT raised in the file where set_error_handler() is called.
Calling undefined functions triggers an E_ERROR, thus it can not be handled by the error callback (or by exception handlers for that matter). All that you can do is set error_reporting to 0.
PS, if you are rolling your own error handler, you should take care to handle correctly the @ operator. From the documentation (emphasis added):
It is important to remember that the standard PHP error handler is completely bypassed. error_reporting() settings will have no effect and your error handler will be called regardless - however you are still able to read the current value of error_reporting and act appropriately. Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.