@错误抑制运算符和set_error_handler

发布于 2024-12-04 04:54:33 字数 254 浏览 3 评论 0原文

我遵循良好的编程实践,并将 PHP 错误记录到文件中,而不是将其显示给用户。我为此使用 set_error_handler()

现在问题来了。例如,我在某处:

@file_exists('/some/file/that/is/outside/openbasedir.txt');

但是尽管有错误抑制运算符,错误消息仍会记录。我不想那样。我希望抑制的错误不要传递给我的错误处理程序。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

简美 2024-12-11 04:54:33

这个答案适用于 PHP 7:

@ 运算符临时将 error_reporting 设置为 0,因此您可以在错误处理程序中测试 error_reporting 的值:

if (error_reporting() == 0)
    return;

或者更好的是,仅记录 error_reporting 中的错误类型:

$error_reporting = error_reporting();
if ( !($error_reporting & $errno) )
    return;

另外看一下 log_errorserror_log 选项,用于自动将错误记录到文件或系统日志中。

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.

青巷忧颜 2024-12-11 04:54:33

也适用于 PHP 7 的解决方案

根据 PHP 文档:

如果您使用 set_error_handler() 设置了自定义错误处理函数,那么它仍然会被调用,但是这个自定义错误处理程序可以(并且应该)调用 error_reporting() ,当触发错误的调用之前时,它将返回 0通过@。

来源: http://php.net/manual/en/language.operators.errorcontrol .php

因此,您可以在错误处理程序中使用以下代码:

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

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");
我很坚强 2024-12-11 04:54:33

PHP8 行为已更改,错误处理程序中的检查 error_reporting() == 0 不再起作用。 PHP8中检查@抑制错误的方法如下:

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

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;
}
眼泪都笑了 2024-12-11 04:54:33

来自手册

警告在 PHP 8.0.0 之前,error_reporting() 在 PHP 内部调用
如果错误被抑制,自定义错误处理程序始终返回 0
@ 运算符。从 PHP 8.0.0 开始,它返回值 E_ERROR |
E_CORE_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | 编译错误E_用户错误| E_RECOVERABLE_ERROR | E_RECOVERABLE_ERROR |
E_PARSE。

这意味着其他答案的解决方案将不起作用:(

@-operator变得完全无法使用恕我直言。

要禁用错误,您必须执行以下操作:

error_reporting(0); // disable

try {
    $res = 10/0;
} catch (Throwable){
    $res = false;
}

error_reporting(-1); // enable

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
凉城 2024-12-11 04:54:33

PHP8 代码 4437 为 @

function myErrorHandler(int $errno, string  $errstr, ?string $errfile, ?int $errline) : void {
    if (error_reporting() !== 4437)
    {
      ......
    }
}

set_error_handler("myErrorHandler", E_ALL);

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);
划一舟意中人 2024-12-11 04:54:33

您实际上应该避免使用 @ 运算符。首先,它很慢,而且我什至称其为有害的。

您应该在 php.ini 文件中有两行:

error_repoting = E_ALL | E_STRICT
display_errors = Off

... 或者,如果您无权访问 php.ini 文件,则在 index.php 的顶部(或任何其他引导文件)您应该添加:

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

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);
寂寞陪衬 2024-12-11 04:54:33

从 PHP 8 开始 - 他们更改了 error_reporting() 以返回非零值“E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE”,在处理错误控制运算符时为 4437。这有点不正统,但请记住 E_WARNING 和其他值没有设置。我认为这是一个“神奇”常数。

有关如何处理错误控制运算符的说明,请参阅错误控制运算符 ,以及设置错误处理程序第一个示例如何忽略未启用的错误。以下是处理错误控制运算符和未启用的错误的示例代码。首先检查错误控制运算符,然后过滤掉未启用的错误,这一点很重要。

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

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...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文