I've tried to catch all exceptions and errors in PHP in a way so that I can deal with them consistently.
This is the code with the exception of the very last bit where I instead pass $e
on to a method that outputs an error page as HTML.
// Only let PHP report errors in dev
error_reporting(ENV === 'dev' ? E_ALL : 0);
// Register handler
set_error_handler("error_handler");
set_exception_handler("error_handler");
register_shutdown_function("error_handler");
function error_handler()
{
// Check for unhandled errors (fatal shutdown)
$e = error_get_last();
// If none, check function args (error handler)
if($e === null)
$e = func_get_args();
// Return if no error
if(empty($e))
return;
// "Normalize" exceptions (exception handler)
if($e[0] instanceof Exception)
{
call_user_func_array(__FUNCTION__, array(
$e[0]->getCode(),
$e[0]->getMessage(),
$e[0]->getFile(),
$e[0]->getLine(),
$e[0]));
return;
}
// Create with consistent array keys
$e = array_combine(array('number', 'message', 'file', 'line', 'context'),
array_pad($e, 5, null));
// Output error page
var_dump($e);
exit;
}
I'm wondering if this is a decent way of doing it or if I have missed anything crucial. Any comments?
1 Answer 1
I don't think that printing raw errors/data to the users is a good idea:
var_dump($e);
They (usually) can't fix it, so it doesn't help them. (See #3 here) It might also contain sensitive information which could help attackers.
Instead of that you should log the errors to a log file, hide the details from the user (don't forget to print a friendly error message) and fix the errors. Your users might not call/mail you when they found a bug. They just simply use one of your competitor's service.
Instead of using the same function for three more or less different purposes:
set_error_handler("error_handler"); set_exception_handler("error_handler"); register_shutdown_function("error_handler");
I'd use three different functions (with proper signatures) which might call a fourth one. It would be cleaner (easier to read, understand and maintain). It would make unnecessary the internal magic with
error_get_last()
,func_get_args()
andinstanceof
.// Only let PHP report errors in dev error_reporting(ENV === 'dev' ? E_ALL : 0);
It seems to me as a code smell: Test Logic in Production. I'd use php.ini to set this, I guess php.ini is a straightforward place for most of the PHP developers to set this instead of a PHP file.