tags:

views:

708

answers:

4

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 in try...catch statements, so I think my best bet is to make a custom error handler for the beginning of my files.

I'm testing it out on a practice page:

function customError($level,$message,$file,$line,$context){
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}

set_error_handler("customError");

echo($imAFakeVariable);

This works fine, returning:

Sorry, an error has occured on line 17. The function that caused the error says Undefined variable: imAFakeVariable.

However, this setup doesn't work for undefined functions.

function customError($level,$message,$file,$line,$context){
echo "Sorry, an error has occured on line $line.<br />";
echo "The function that caused the error says $message.<br />";
die();
}

set_error_handler("customError");

imAFakeFunction();

This returns:

Fatal error: Call to undefined function: imafakefunction() in /Library/WebServer/Documents/experimental/errorhandle.php on line 17

Why isn't my custom error handler catching undefinedd functions? Are there other problems that this will cause?

Thanks, Jason

+1  A: 

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.

John Millikin
+1  A: 

One of the best ways to get help on a PHP topic is to look through the function reference on the PHP.net website. You'll often find that someone has had the same problem and will have provided sample code to show how to work around it.

In regard to your question, have a look through the set_error_handler page. There are a lot of functions there - one of which should fit your needs.

different
+1  A: 

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.

Cd-MaN
+3  A: 

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 of E_STRICT raised in the file where set_error_handler() is called."

This is not exactly true. set_error_handler() can't handle them, but ob_start() can handle at least E_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.

Ross