在PHP

时间:2017-10-31 16:57:36

标签: php error-handling error-reporting

为PHP系统编写了一个自定义错误处理程序我试图弄清楚如何确定错误报告级别(可以通过error_reporting()获得)是否全局设置为Off(0)或仅使用@ prefix

禁用该行

当前的问题是,对于这两种情况,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

1 个答案:

答案 0 :(得分:2)

除了error_reporting()之外,您还可以使用ini_get('error_reporting')检查错误报告级别。从理论上讲,这是相似的,但它有一个微妙的差异,使它对你正在尝试做的事情有价值。

如果已使用error_reporting(0)全局禁用错误报告,则ini_get('error_reporting')将返回字符串0。但是,如果错误报告单独存在并且该行以@为前缀,则它将返回非零值(现有INI指令的值)。

因此,您可以比较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

经过一番思考,我想出了这个主意。只是一个警告,这似乎非常hacky和低效,但我开始认为这可能是唯一的方法。

如果你正在关注set_error_handler的PHP文档中的示例,那么自定义错误处理程序的函数签名可能如下所示:

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)上为我工作。