views:

89

answers:

1

Please tell me if this is correct. In my error handler, I need to be able to detect when the @ error-control operator was used to suppress errors, because some external libraries (sadly) use it a lot. Execution of the script should continue, just like when you don't use custom error handlers.

When the at-sign is used, PHP temporarily sets error_reporting to 0. So at the start of a script we set error_reporting to any value but zero - we can now do some beautiful IF/ELSE magic. To avoid any errors being shown at the frontend, we also set display_errors to 0, this will override error_reporting (but we can still use it's value for magic).

<?php

ini_set('display_errors',0);
error_reporting(E_ALL);

function error_handler($errno, $errstr, $errfile, $errline)
{
    if (error_reporting()===0) return;
    else die();
}

set_error_handler('error_handler');

//This issues an error, but the handler will return and execution continues.
//Remove the at-sign and the script will die()
@file();

echo 'Execution continued, hooray.';
?>

So.. Are there no catches here? Except the one where the external library overrides my error handling.. (any tips on that?)

+1  A: 

Hi,

Considering what your script does, and some user notes on the @ operator manual page, it seems what you are doing is OK.

For instance, taras says :

I was confused as to what the @ symbol actually does, and after a few experiments have concluded the following:

  • the error handler that is set gets called regardless of what level the error reporting is set on, or whether the statement is preceeded with @

  • it is up to the error handler to impart some meaning on the different error levels. You could make your custom error handler echo all errors, even if error reporting is set to NONE.

  • so what does the @ operator do? It temporarily sets the error reporting level to 0 for that line. If that line triggers an error, the error handler will still be called, but it will be called with an error level of 0

And the set_error_handler manual page seems to confirm that :

Of particular note is that this value will be 0 if the statement that caused the error was prepended by the @ error-control operator.

Here too, there are some user notes that can be useful ; for instance, this one (see the begining of the code)


Still, if what you want is to "disable" the effect of the @ operator (not sure I understood the question correctly ; this might help you anyway), to be able to get the error messages while you are on your development environment, you can install the scream extension (pecl, manual)

Provided you configure it the right way, setting this in your php.ini (after installating/loading the extension, of course) :

scream.enabled = 1

This extension will simply disable the @ operator.


And here's an example (quoting the manual) :

<?php
// Make sure errors will be shown
ini_set('display_errors', true);
error_reporting(E_ALL);

// Disable scream - this is the default and produce an error
ini_set('scream.enabled', false);
echo "Opening http://example.com/not-existing-file\n";
@fopen('http://example.com/not-existing-file', 'r');

// Now enable scream and try again
ini_set('scream.enabled', true);
echo "Opening http://example.com/not-existing-file\n";
@fopen('http://example.com/another-not-existing-file', 'r');
?>

And this will output :

Opening http://example.com/not-existing-file
Opening http://example.com/not-existing-file

Warning: fopen(http://example.com/another-not-existing-file): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in example.php on line 14


I am not sure I would use this extension on a production server (where I never want errors displayed), but it is very useful on a development machine, when using old code, on an application/library that uses @ operator extensivly...

Pascal MARTIN
+1. This confirmation was all I needed. The scream extension seems usefull, might check into that. Not in todays case though, I just want an external library to be able to do it's thing - as if my application wasn't there.
Vincent W