Error Control Operators

PHP supports one error control operator: the at sign (@). When
prepended to an expression in PHP, any error messages that might
be generated by that expression will be ignored.

If you have set a custom error handler function with
set_error_handler() then it will still get
called, but this custom error handler can (and should) call error_reporting()
which will return 0 when the call that triggered the error was preceded by an @.

If the track_errors
feature is enabled, any error message generated by the expression
will be saved in the variable
$php_errormsg.
This variable will be overwritten on each error, so check early if you
want to use it.

// this works for any expression, not just functions:$value = @$cache[$key];// will not issue a notice if the index $key doesn't exist.

?>

Note:
The @-operator works only on
expressions. A simple rule
of thumb is: if you can take the value of something, you can prepend
the @ operator to it. For instance, you can prepend it to variables,
function and include calls, constants, and
so forth. You cannot prepend it to function or class definitions,
or conditional structures such as if and
foreach, and so forth.

Currently the "@" error-control operator prefix will even disable
error reporting for critical errors that will terminate script
execution. Among other things, this means that if you use "@" to
suppress errors from a certain function and either it isn't
available or has been mistyped, the script will die right there
with no indication as to why.

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

There is no reason to NOT use something just because "it can be misused". You could as well say "unlink is evil, you can delete files with it so don't ever use unlink".

It's a valid point that the @ operator hides all errors - so my rule of thumb is: use it only if you're aware of all possible errors your expression can throw AND you consider all of them irrelevant.

A simple example is<?php

$x = @$a["name"];

?>There are only 2 possible problems here: a missing variable or a missing index. If you're sure you're fine with both cases, you're good to go. And again: suppressing errors is not a crime. Not knowing when it's safe to suppress them is definitely worse.

If you're wondering what the performance impact of using the @ operator is, consider this example. Here, the second script (using the @ operator) takes 1.75x as long to execute...almost double the time of the first script.

So while yes, there is some overhead, per iteration, we see that the @ operator added only .005 ms per call. Not reason enough, imho, to avoid using the @ operator.

Error suppression should be avoided if possible as it doesn't just suppress the error that you are trying to stop, but will also suppress errors that you didn't predict would ever occur. This will make debugging a nightmare.

It is far better to test for the condition that you know will cause an error before preceding to run the code. This way only the error that you know about will be suppressed and not all future errors associated with that piece of code.

There may be a good reason for using outright error suppression in favor of the method I have suggested, however in the many years I've spent programming web apps I've yet to come across a situation where it was a good solution. The examples given on this manual page are certainly not situations where the error control operator should be used.

After some time investigating as to why I was still getting errors that were supposed to be suppressed with @ I found the following.

1. If you have set your own default error handler then the error still gets sent to the error handler regardless of the @ sign.

2. As mentioned below the @ suppression only changes the error level for that call. This is not to say that in your error handler you can check the given $errno for a value of 0 as the $errno will still refer to the TYPE(not the error level) of error e.g. E_WARNING or E_ERROR etc

3. The @ only changes the rumtime error reporting level just for that one call to 0. This means inside your custom error handler you can check the current runtime error_reporting level using error_reporting() (note that one must NOT pass any parameter to this function if you want to get the current value) and if its zero then you know that it has been suppressed.<?php// Custom error handlerfunction myErrorHandler($errno, $errstr, $errfile, $errline){ if ( 0 == error_reporting () ) {// Error reporting is currently turned off or suppressed with @return; }// Do your normal custom error reporting here}?>

Better use the function trigger_error() (http://de.php.net/manual/en/function.trigger-error.php)to display defined notices, warnings and errors than check the error level your self. this lets you write messages to logfiles if defined in the php.ini, outputmessages in dependency to the error_reporting() level and suppress output using the @-sign.

If you use the ErrorException exception to have a unified error management, I'll advise you to test against error_reporting in the error handler, not in the exception handler as you might encounter some headaches like blank pages as error_reporting might not be transmitted to exception handler.

In PHP it is extremely beneficial to turn all notices into exceptions. This helps in creating bug free code through finding errors sooner rather than later. It also helps reduce the impact of bugs as code when entering an erroneous state ends sooner rather than later and at all. In the worst case without that you can have much more scenarios where code fails yet appears as though it succeeded.

However there are rare cases in which notices and warnings are produced where the above behavour might be unproductive. Worse yet your error handling will kick out that exception before the function gets to return.

They are rare cases such as socket handling where certain states are expressed through errors causing ambiguity.

While you should definitely not be too liberal with the @ operator, I also disagree with people who claim it's the ultimate sin.

For example, a very reasonable use is to suppress the notice-level error generated by parse_ini_file() if you know the .ini file may be missing.In my case getting the FALSE return value was enough to handle that situation, but I didn't want notice errors being output by my API.

If you want to log all the error messages for a php script from a session you can use something like this:<?php session_start(); function error($error, $return=FALSE) { global $php_errormsg; if(isset($_SESSION['php_errors'])) {$_SESSION['php_errors'] = array(); }$_SESSION['php_errors'][] = $error; // Maybe use $php_errormsgif($return == TRUE) {$message = ""; foreach($_SESSION['php_errors'] as $php_error) {$messages .= $php_error."\n"; } return $messages; // Or you can use use $_SESSION['php_errors']}}?>Hope this helps someone...

I was wondering if anyone (else) might find a directive to disable/enable to error operator would be a useful addition. That is, instead of something like (which I have seen for a few places in some code):

A shame you can't use curly brackets above to enclose multiple lines of code, like you can with an if statement or a loop. It could make for a single long line of code. You could always call a function instead.