检测(在自定义错误处理程序中)PHP 错误是否确实被 @ 抑制

发布于 2024-12-04 14:47:46 字数 458 浏览 0 评论 0原文

上下文:

我的应用程序有三个环境:开发(本地)、测试/登台(产品服务器)、生产。该应用程序知道哪个是哪个。登台和生产的错误报告均为 0,因此永远不会显示错误。在开发中,我希望立即看到错误,并且希望看到它们发生的位置,所以不是在某些日志中,而是在代码的结果中。

但是,我不想看到我用 @ 明确抑制的错误。我一直在使用 fsockopen ,当它无法连接时会抛出警告。我接受无连接,但不想看到错误。甚至不在开发中。

显然,所有错误都会通过自定义错误处理程序,即使它们在代码中被抑制。

我的错误处理程序只有 4 个参数:errno、error、file、line。从这些我看不出错误最初是否被抑制。如果我可以看到那里,我可以选择是否打印错误(现在我总是这样做,如果 env=dev)。

有什么想法吗?或者也许如何完全忽略被抑制的错误(以便它们甚至不会到达自定义错误处理程序)?

Context:

I have three environments for an app: dev (local), test/staging (prod server), production. The app knows which is which. Error reporting on both staging and production is 0, so errors are never shown. On dev I want to see errors immediately and I want to see them where they happen, so not in some log, but in the code's result.

However, I don't want to see the errors I have explicitly suppressed with @. I've been using fsockopen and that throws a warning when it can't connect. I accept the no-connection, but don't want to see the error. Not even on dev.

Apparantly all errors go though the custom error handler, even if they were suppressed in the code.

My error handler has only 4 arguments: errno, error, file, line. From those I can't see whether the error was originally suppressed or not. If I can see that there, I can choose whether to print the error (right now I always do, if env=dev).

Any ideas? Or maybe on how to completely ignore suppressed errors (so that they don't even reach the custom error handler)?

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

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

发布评论

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

评论(4

菊凝晚露 2024-12-11 14:47:46

set_error_handler 手册页。

如果导致错误的语句是,[error_reporting()] 值将为 0
由 @ 错误控制运算符前置

当您使用错误控制运算符 @ 时,发生的情况是这样的:

  1. 错误报告设置为 0(无错误) - error_reporting(0)
  2. 表达式被求值
  3. 错误报告被设置回以前的值(即重新打开)

上面的引用有点令人困惑,它指的是 error_reporting 返回当前设置。如果您使用控制运算符抑制了错误,则调用 error_reporting() 将返回 0。

因此,如果您知道,您已将其设置为非零(即您是报告一些错误)并且它返回零,您知道错误已被抑制。

如果您检测到被抑制的错误并想知道它是什么,您可以在变量 $php_errormsg(如果 track_errorsphp.ini 中设置为 true) 。

请注意,错误控制运算符会导致大量开销,因为它每次使用时都会更改错误报告级别两次。它会减慢你的脚本速度。

There's a hint to this in the set_error_handler manual page.

[the error_reporting()] value will be 0 if the statement that caused the error was
prepended by the @ error-control operator

When you use the error control operator @, what is happening is this:

  1. error reporting is set to 0 (no errors) - error_reporting(0)
  2. the expression is evaluated
  3. error reporting is set back to the previous value (ie turned back on)

The slightly confusing quote above refers to the fact that error_reporting returns the current setting. If you have suppressed the error with the control operator, calling error_reporting() will return 0.

Therefore, if you know you have set it to non-zero (ie you are reporting some errors) and it returns zero, you know the error was suppressed.

If you detect a suppressed error and want to know what it was, you can find it in the variable $php_errormsg (if track_errors is set to true in php.ini).

Note that the error control operator causes a lot of overhead, as it changes the error reporting level twice each time it is used. It will slow down your script.

哆啦不做梦 2024-12-11 14:47:46

对于 PHP 8.0

因此,在 PHP 8.0 中,您不再能够仅通过检查 error_reporting() == 0 来判断错误/警告/通知等是否被抑制(使用 @)。

相反,它现在是一段相当长的带有常量的按位运算符,在此处的警告框中进行了描述:https://www.php.net/manual/en/language.operators.errorcontrol.php

修复 PHP 7.x 和 8.x

在您的自定义错误处理程序中,如果您想要知道您的错误是否被 @ 符号抑制,请使用如下内容:

$PHP_8_SUPPRESSED = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE;
$er = error_reporting();  
    
if ($er === 0 || $er === $PHP_8_SUPPRESSED) { 
  // do code because it was suppressed.  Ex: return FALSE, etc.
} 

在撰写本文时,$PHP_8_SUPPRESSED 将等于整数值 4437,但它可能是最好不要对其进行硬编码,因为 PHP 的未来版本可能会更改这些常量值。

快速旁注:我真的希望他们刚刚创建了一个名为“E_SUPPRESSED_ERROR”的新常量或类似的东西,我们可以检查。但遗憾的是他们没有!

For PHP 8.0

So in PHP 8.0, you can no longer tell if the error/warning/notice, etc, was suppressed (using @) simply by checking if error_reporting() == 0.

Instead, it is now a fairly long piece of bitwise operators with constants, described in a warning box here: https://www.php.net/manual/en/language.operators.errorcontrol.php

Fix for both PHP 7.x and 8.x

In your custom error handler, if you want to tell if your error was suppressed with the @ sign, use something like this:

$PHP_8_SUPPRESSED = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE;
$er = error_reporting();  
    
if ($er === 0 || $er === $PHP_8_SUPPRESSED) { 
  // do code because it was suppressed.  Ex: return FALSE, etc.
} 

At the time of this writing, $PHP_8_SUPPRESSED will equal integer value 4437, but it's probably best not to hard-code that, since future versions of PHP might change these constant values.

Quick side note: I really wish they had just created a new constant called "E_SUPPRESSED_ERROR" or something like that we could check. But sadly they did not!

月朦胧 2024-12-11 14:47:46

处理 php 错误的正确方法

  • 是不要使用 error_reporting
  • 安装错误到异常处理程序 ( http://www.php.net/manual/en/class.errorexception.php ,示例 1) 并将所有 php“错误”转换
  • 为主代码中的异常,使用try-catch在适当的地方
  • 安装异常处理程序来捕获未捕获的异常在主代码中。该处理程序是输出和/或记录错误的唯一位置。
  • 不要使用@。在极少数情况下,您想忽略错误,请使用空 catch 块,
  • 使用一些 愚蠢的技巧来捕获“致命”错误。更好的是,联系 php 小组并尝试说服他们在脚本中处理“致命”错误。

A proper way to handle errors in php

  • do not use error_reporting
  • install an errors-to-exceptions handler ( http://www.php.net/manual/en/class.errorexception.php , example 1) and convert all php "errors" to exceptions
  • in your main code, use try-catch where appropriate
  • install an exception handler to catch exceptions not caught in the main code. This handler is the only place where you output and/or log errors.
  • do not use @. In a rare case you want to ignore an error, use an empty catch block
  • use some stupid trick to catch "fatal" errors. Better yet, contact php group and try to convince them to make "fatal" errors handleable in scripts.
七秒鱼° 2024-12-11 14:47:46

将其也添加到您的处理程序中

   // error was suppressed with the @-operator
    if (0 === error_reporting()) { return false;}

Add this too your handler

   // error was suppressed with the @-operator
    if (0 === error_reporting()) { return false;}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文