检测(在自定义错误处理程序中)PHP 错误是否确实被 @ 抑制
上下文:
我的应用程序有三个环境:开发(本地)、测试/登台(产品服务器)、生产。该应用程序知道哪个是哪个。登台和生产的错误报告均为 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
set_error_handler
手册页。当您使用错误控制运算符
@
时,发生的情况是这样的:error_reporting(0)
上面的引用有点令人困惑,它指的是
error_reporting
返回当前设置。如果您使用控制运算符抑制了错误,则调用error_reporting()
将返回 0。因此,如果您知道,您已将其设置为非零(即您是报告一些错误)并且它返回零,您知道错误已被抑制。
如果您检测到被抑制的错误并想知道它是什么,您可以在变量
$php_errormsg
(如果track_errors
在php.ini
中设置为true
) 。请注意,错误控制运算符会导致大量开销,因为它每次使用时都会更改错误报告级别两次。它会减慢你的脚本速度。
There's a hint to this in the
set_error_handler
manual page.When you use the error control operator
@
, what is happening is this:error_reporting(0)
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, callingerror_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
(iftrack_errors
is set totrue
inphp.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.
对于 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
将等于整数值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:
At the time of this writing,
$PHP_8_SUPPRESSED
will equal integer value4437
, 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!
处理 php 错误的正确方法
error_reporting
@
。在极少数情况下,您想忽略错误,请使用空 catch 块,A proper way to handle errors in php
error_reporting
@
. In a rare case you want to ignore an error, use an empty catch block将其也添加到您的处理程序中
Add this too your handler