Reputation: 48715
I am following good programming practices and I am logging the PHP errors to file instead of displaying it to user. I use set_error_handler()
for that.
Now the problem. For example, I have somewhere:
@file_exists('/some/file/that/is/outside/openbasedir.txt');
But despite the error suppression operator, the error message logs. I don't want that. I want suppressed errors not to pass to my error handler.
Upvotes: 26
Views: 3585
Reputation: 21
Starting with PHP 8 - They changed error_reporting() to return the non-zero value "E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE" which is 4437 when handling error control operators. This is a bit unorthodox, but keep in mind that E_WARNING and other values are not set. I consider that a "magic" constant.
See Error Control Operators for description how error control operators are handled, and Set Error Handler first example how to ignore errors that are not enabled. Here is sample code to handle both error control operators and errors that are not enabled. It is important to check for error control operator first, then filter out the errors that are not enabled.
function errorHandler($errno, $errstr, $errfile, $errline)
{
// catch error control operator and return
if (error_reporting() ===
E_ERROR |
E_CORE_ERROR |
E_COMPILE_ERROR |
E_USER_ERROR |
E_RECOVERABLE_ERROR |
E_PARSE
) {
return false;
}
// catch errors not being flagged
if (!(error_reporting() & $errno)) {
return false;
}
...rest of error handler logic...
}
Upvotes: 0
Reputation: 11
PHP8 code 4437 for @
function myErrorHandler(int $errno, string $errstr, ?string $errfile, ?int $errline) : void {
if (error_reporting() !== 4437)
{
......
}
}
set_error_handler("myErrorHandler", E_ALL);
Upvotes: 1
Reputation: 99879
This answer applies at PHP 7:
The @
operator temporarily sets error_reporting to 0, so you can test the value of error_reporting in your error handler:
if (error_reporting() == 0)
return;
Or even better, log only error types that are in error_reporting:
$error_reporting = error_reporting();
if ( !($error_reporting & $errno) )
return;
Also take a look at the log_errors
and error_log
options, for automatically logging errors to a file or to syslog.
Upvotes: 36
Reputation: 3583
PHP8 behavior has changed and checking error_reporting() == 0
in the error handler no longer works. The way to check for errors suppressed with @ in PHP8 is as follows:
function errorHandler($err_severity, $err_msg, $err_file, $err_line)
{
// Skip errors suppressed by @
if (!(error_reporting() & $err_severity)) {
return true;
}
// Error handling here
return false;
}
Upvotes: 5
Reputation: 129
From manual:
Warning Prior to PHP 8.0.0, the error_reporting() called inside the custom error handler always returned 0 if the error was suppressed by the @ operator. As of PHP 8.0.0, it returns the value E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE.
This means that solutions from other answers will not work :(
The @-operator became completely unusable imho.
To disable errors you will have to do the following:
error_reporting(0); // disable
try {
$res = 10/0;
} catch (Throwable){
$res = false;
}
error_reporting(-1); // enable
Upvotes: 1
Reputation: 1372
Solution that also works for PHP 7
According to the PHP docs:
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 @.
Source: http://php.net/manual/en/language.operators.errorcontrol.php
So you can use the following code in your error handler:
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
if (error_reporting() == 0) {
/// @ sign temporary disabled error reporting
return;
}
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");
Upvotes: 9
Reputation: 58444
You should actually avoid usage of @
operator. First of all, it is slow, and I would as far as to call it harmful.
What you should have instead is in php.ini
file have two line:
error_repoting = E_ALL | E_STRICT
display_errors = Off
... or , if you do not have access to the php.ini file , then at the top of index.php (or any other bootstrap file) you should add :
error_reporting( E_ALL | E_STRICT );
ini_set('display_errors', 0);
Upvotes: 0