开发者

@ error suppression operator and set_error_handler

开发者 https://www.devze.com 2023-04-04 07:30 出处:网络
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.

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 suppr开发者_如何学Cessed errors not to pass to my error handler.


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.


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");


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


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;
}


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);


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);
0

精彩评论

暂无评论...
验证码 换一张
取 消