Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there any "gotchas" with this approach to handling errors in PHP?

I'm a relative newbie to PHP, but it seems to me that PHP's error handling is a bit of a ghetto, with errors and warnings interspersed with exceptions (and don't get me started on die()). As such, I'm not certain how best to go about creating, interpreting, and handling all error cases in my application.

My general plan of attack is roughly as follows:

  1. Convert all warnings/errors into Exceptions, using set_error_handler() to wrap the errors as they come.
  2. Code defensively, preemptively checking for things I expect to go wrong. Throw exceptions only when I can't handle the error directly. Usual try/catch blocks will be in place when needed, to handle exceptions I don't throw myself.
  3. Wrap my entire application (i.e. my index.php point-of-entry file) in it's own try/catch. Should that fail, I'll throw an HTTP 500 and show a suitable error page. Presumably this page will be a single, pre-compiled file rather than a collection of header/body/footer includes - this is largely so that I can still cover weird exceptions like a garbled template file. I assume this is why Google's 500-class error page looks so much different from everything else they put out.
  4. As a corollary to #2 and #3, since I'm expecting to handle everything upfront, if I decide to throw my own exception, I'm also expecting not to catch the error, and instead let it bubble all the way up to my top level handler. The thinking here is that if I can't handle it when it happens, I'm probably ill-equipped to handle it anywhere else. I'm thinking of giving these errors their own subclass - perhaps CriticalErrorException - that can be identified directly in my logs/spawn an email so I can look into it quickly. In general, I'm expecting these to be things that may happen in dev, but should be ironed out by production.
  5. Any error that makes it to the top gets logged in the database, with failover to a log file. Critical errors, as indicated above, trigger an email. If the reporting fails over to the file - i.e. there's a DB error - that would also trigger an email.

I think this covers most cases pretty well, but as I said I'm very new to PHP so I don't know if there are corner cases or weird behaviours that I'm overlooking.

What are the flaws in my plan? How can I overcome them?

like image 604
AgentConundrum Avatar asked Nov 14 '22 05:11

AgentConundrum


1 Answers

Overall, the strategy of letting unexpected exceptions bubble up to a top catch block and then serve out a HTTP 500 is fine (many frameworks do just that).

I don't quite agree with making a CriticalErrorException -- maybe you don't expect to catch something now, but you might expand your error handling in the future (possibly in the face of additional application requirements). Just throw whatever is natural. A simple Exception is fine in most cases.

Regarding PHP errors: you do not strictly need to convert E_ERROR into an exception (it will kill your app anyway, and will show up in the error log as well). You would do well to handle E_NOTICE though, as notices almost always mean that there's something not right with the code.

Finally, when talking about PHP functions that raise warnings, I would go with this:

// Assume that php_function() raises E_WARNING and returns FALSE on error
// WARNING: if you have defined a custom error handler, IT WILL STILL BE CALLED
//          even though the @ operator suppresses the error
$result = @php_function($argument); // suppress error
if (!$result) {
    // error handling here
}

instead of this:

try {
    $result = php_function($argument);
}
catch (Exception $ex) {
    // error handling here
}

The reason being that converting to an exception doesn't really buy you anything when you intend to react to the error immediately. On the contrary, the first code snippet will "tell" a developer reading it to look up the documentation for php_function if more info on its error handling strategy is needed. The second code snippet will require the developer to have knowledge about error handling specifically as implemented in your app.

Update:

I 'm not saying that you should use @ to just ignore errors coming out of function calls. What I am saying is that, when using legacy PHP functions that behave this way, and when you are fully prepared to handle the error and recover from it, then of course it should no longer be considered an "error" regarding your application's execution. In this specific case, I recommend suppressing it so that it doesn't get reported as well.

like image 117
Jon Avatar answered Nov 17 '22 07:11

Jon