上下文:
我有一个应用程序有三个环境:开发(本地(、测试/暂存(生产服务器(、生产。该应用程序知道哪个是哪个。暂存和生产上的错误报告均为 0,因此永远不会显示错误。在 dev 上,我想立即看到错误,我想在它们发生的地方看到它们,所以不是在某些日志中,而是在代码的结果中。
但是,我不想看到我用@
明确禁止的错误。我一直在使用fsockopen
,当它无法连接时会发出警告。我接受无连接,但不想看到错误。甚至在开发上也没有。
显然,所有错误都通过自定义错误处理程序,即使它们在代码中被禁止。
我的错误处理程序只有 4 个参数:errno、错误、文件、行。从那些我看不出错误最初是否被抑制。如果我能在那里看到,我可以选择是否打印错误(现在我总是这样做,如果 env=dev(。
有什么想法吗?或者也许关于如何完全忽略抑制的错误(这样它们甚至不会到达自定义错误处理程序(?
在set_error_handler
手册页中对此有提示。
[
error_reporting()
] 值将为 0,如果导致错误的语句是 由 @ 错误控制运算符预置
当您使用错误控制运算符 @
时,正在发生如下情况:
- 错误报告设置为 0(无错误(-
error_reporting(0)
- 计算表达式
- 错误报告被设置回以前的值(即重新打开(
上面有点令人困惑的引用是指error_reporting
返回当前设置的事实。如果使用控制运算符禁止显示错误,则调用error_reporting()
将返回 0。
因此,如果您知道已将其设置为非零(即您报告了一些错误(并且它返回零,则表明该错误已被抑制。
如果检测到抑制错误并想知道它是什么,则可以在变量$php_errormsg
中找到它(如果track_errors
设置为 php.ini
中的true
(。
控制运算符会导致大量开销,因为它每次使用时都会更改两次错误报告级别。它会减慢您的脚本速度。
对于 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"的新常量或我们可以检查的类似常量。但可悲的是他们没有!
在 php 中处理错误的正确方法
- 请勿使用
error_reporting
- 安装一个错误到异常处理程序(http://www.php.net/manual/en/class.errorexception.php,示例 1(并将所有 PHP"错误"转换为异常
- 在主代码中,在适当的情况下使用 try-catch
- 安装异常处理程序以捕获主代码中未捕获的异常。此处理程序是输出和/或记录错误的唯一位置。
- 不要使用
@
.在极少数情况下,您希望忽略错误,请使用空的捕获块 - 使用一些愚蠢的技巧来捕获"致命"错误。更好的是,联系php组并尝试说服他们在脚本中处理"致命"错误。