确定 error_reporting(0) 和 PHP 中的前置 @ 之间的区别
Determining the difference between error_reporting(0) and pre-pending @ in PHP
为 PHP 系统编写了自定义错误处理程序后,我想弄清楚如何确定错误报告级别(可以通过 error_reporting()) has been globally set to Off (0) or has been disabled for that line only using the @ prefix
获得)
目前的问题是,对于这两种情况,error_reporting() 函数 returns 0
更新 #1
不幸的是,此示例不适用于 CentOS 6.8 上的 PHP 5.3.3,因为 ini_get() 函数 returns 与 error_reporting()[ 的值相同=14=]
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')
查看报错级别。从理论上讲,这很相似,但它有一个细微的差别,这使得它对您尝试做的事情很有价值。
如果已使用 error_reporting(0)
全局禁用错误报告,则 ini_get('error_reporting')
将 return 字符串 0
。但是如果错误报告被单独留下并且该行以 @
为前缀,它将 return 一个非零值(现有 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)上对我有用。
为 PHP 系统编写了自定义错误处理程序后,我想弄清楚如何确定错误报告级别(可以通过 error_reporting()) has been globally set to Off (0) or has been disabled for that line only using the @ prefix
获得)目前的问题是,对于这两种情况,error_reporting() 函数 returns 0
更新 #1
不幸的是,此示例不适用于 CentOS 6.8 上的 PHP 5.3.3,因为 ini_get() 函数 returns 与 error_reporting()[ 的值相同=14=]
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')
查看报错级别。从理论上讲,这很相似,但它有一个细微的差别,这使得它对您尝试做的事情很有价值。
如果已使用 error_reporting(0)
全局禁用错误报告,则 ini_get('error_reporting')
将 return 字符串 0
。但是如果错误报告被单独留下并且该行以 @
为前缀,它将 return 一个非零值(现有 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)上对我有用。