How to ignore @ errors in a custom PHP error handler

The PHP error control operator@ — when prepended to an expression, suppresses or ignores any error messages that might be generated by that expression. For example :

@fopen ('http://incorrect.url.com');

But when one defines a custom error handler in PHP, it is called even when the @ is used, which leads to a lot of frustration when one does not know the workaround to this ‘problem’ – let me give you the solution :

Custom error handler

As I’ve explained in Error vs Exception, Part 1, in PHP a custom error handler is set in the following way :

set_error_handler('a_callback_function', $error_type_bitmask);

The error handler is then called for the runtime error types defined by the bitmask, which might include E_WARNING, E_NOTICE, most E_STRICT as well as errors triggered with trigger_error(). But the error handler is also called for those errors even when the error is prepended by the @ error control operator. This obviously creates a problem for you if you’d like it to continue ignoring those errors as before.

@ has its uses

Now one really should use the @ operator very sparingly, handling errors instead of suppressing them. But there are a small number of situations I can think of where one might need to suppress some PHP errors. Let me offer two examples :

  • You could be using some large external library which has made use of the @, and so need to be able to ignore those errors as the author of the library intended, otherwise your program is going to trip up where it doesn’t need to. You could edit the library, but it might take a lot of time, and your changes would again have to be applied each time the author releases an update to the library.
  • Another example might be when the fopen function is used to open an external URL, and the URL cannot be opened for one of many possible reasons. The function returns false to indicate a fail, which is great, but to quote the PHP manual, an error of level E_WARNING is generated too, not so great — it should really result in an exception being thrown instead, as this is an irregular situation, but one which should be expected. In this case one would like to be able to ignore the error, and continue with the program execution, explicitly responding in an appropriate way – exactly what exceptions are for! There is, however, a way to convert the error to an exception and so avoid using the @ in this situation. In your custom error handler (which is where we find ourselves in this post), throw an ErrorException – this then requires you to explicitly catch and handle it in the code that was using the @ before, which is a better way of handling errors, as I’ve explained here.

Solution

So you see that the only time that the @ absolutely has to be used, is when one is using an outdated external library. That cannot always be helped, but you should check to see whether the library hasn’t perhaps been updated in the meantime, or whether you can find a library that makes use of better coding practice.

That being said, if one has to use the old library and need to ignore the @, the way to do it actually comes straight from the PHP manual’s set_error_handler page, where it states the following :

…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.

This means that you can simply check for the value of error_reporting() at the start of your custom error handler, and a value of 0 will indicate that the error was prepended by the @ to suppress it :

if (error_reporting() === 0) {
    // continue script execution, skipping standard PHP error handler
    return true;
}

That’s it, @ errors can again be ignored, but with all the added benefits of a custom error handler, and best coding practice!

Leave a Reply