提问人:Liam Freke 提问时间:11/1/2017 最后编辑:Liam Freke 更新时间:11/1/2017 访问量:121
确定 PHP 中 error_reporting(0) 和 pre-pending @ 之间的区别
Determining the difference between error_reporting(0) and pre-pending @ in PHP
问:
在为 PHP 系统编写了一个自定义错误处理程序后,我试图弄清楚如何确定错误报告级别(可以通过 error_reporting()) 获取)是否已全局设置为 Off (0) 或仅使用 @ 前缀禁用该行
目前的问题是,对于这两种情况,error_reporting() 函数都返回 0
更新 #1
不幸的是,这个例子不适用于 CentOS 6.8 上的 PHP 5.3.3,因为 ini_get() 函数返回与 error_reporting() 相同的值
function errhandle($errno, $errstr, $errfile, $errline) {
if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '@ was used';
}
}
set_error_handler('errhandle');
echo error_reporting()."\n";
echo @$arr['name'];
// Prints
22527
error_reporting(0) was used
答:
除了 之外,还可以使用 检查错误报告级别。从理论上讲,这是相似的,但它有一个微妙的区别,使它对你正在尝试做的事情很有价值。error_reporting()
ini_get('error_reporting')
如果错误报告已全局禁用,则将返回字符串 .但是,如果错误报告被单独保留,并且该行以 为前缀,它将返回一个非零值(现有 INI 指令的值)。error_reporting(0)
ini_get('error_reporting')
0
@
因此,您可以比较 2 个值并准确确定发生了什么:
if (error_reporting() === 0 && error_reporting() === (int)ini_get('error_reporting')) {
echo 'error_reporting(0) was used';
} else if (error_reporting() === 0 && error_reporting() !== (int)ini_get('error_reporting')) {
echo '@ was used';
}
这只是您可以在自定义错误处理程序中执行的条件类型的一个示例。如果它不是你想要的,请告诉我,我会尝试调整它。
在我的 PHP 7.1.2(Windows 上的 CLI)上进行了本地测试。
更新 #1
经过一番思考,我想出了这个主意。只是一个警告,这似乎非常黑客和低效,但我开始认为这可能是唯一的方法。
如果您按照 PHP 文档中的示例进行set_error_handler,那么自定义错误处理程序的函数签名可能如下所示:
function myErrorHandler($errno, $errstr, $errfile, $errline)
换句话说,您拥有发生错误的文件和行号。您可以使用此信息打开文件本身,查看该行号,解析标记并查找字符。代码如下所示:@
function myErrorHandler($errno, $errstr, $errfile, $errline) {
$errfileContents = file($errfile);
$errlineContents = $errfileContents[$errline - 1];
$tokens = token_get_all('<?php ' . $errlineContents . ' ?>');
if (error_reporting() === 0) {
if (in_array('@', $tokens)){
echo '@ was used';
} else {
echo 'error_reporting(0) was used';
}
}
}
显然,您可以通过检查是否同时使用了这两种技术或两者都没有使用来扩展该条件。
无论如何,它很丑陋,但它在我的 PHP 5.6.6(Windows 上的 CLI)上对我有用。
评论
There is no reason to NOT use something just because "it can be misused". You could as well say "unlink is evil, you can delete files with it so don't ever use unlink". It's a valid point that the @ operator hides all errors - so my rule of thumb is: use it only if you're aware of all possible errors your expression can throw AND you consider all of them irrelevant.