处理 @ 错误控制运算符
多年来,许多 PHP 开发人员使用 @
错误控制运算符来掩盖错误。在使用不可靠的 PHP 库和编写糟糕的代码时尤其如此。不幸的是,这种用法的最终结果只能是传播不良代码!
许多 PHP 开发人员一厢情愿地认为,当他们使用 @
操作符来阻止错误显示时,问题似乎就神奇地消失了!请相信我:问题并没有消失!在本节中,我们首先考察 @
操作符的传统用法,然后考察 PHP 8 中 @
操作符的变化。
有关传统 |
@ 运算符用法
在介绍代码示例之前,我们必须再次强调,我们并不提倡使用这种机制!相反,您应该在任何情况下都避免使用这种机制。如果出现错误信息,最好的解决办法是修复错误,而不是让它保持沉默!
在下面的代码示例中,定义了两个函数。bad()
函数故意触发一个错误。worse()
函数包含一个存在解析错误的文件。请注意,在调用这些函数时,@
符号会出现在函数名之前,从而抑制错误输出:
// /repo/ch03/php8_at_silencer.php
function bad() {
trigger_error(__FUNCTION__, E_USER_ERROR);
}
function worse() {
return include __DIR__ . '/includes/
causes_parse_error.php';
}
echo @bad();
echo @worse();
echo "\nLast Line\n";
在 PHP 7 中,根本没有输出,如下所示:
root@php8_tips_php7 [ /repo/ch03 ]# php php8_at_silencer.php
root@php8_tips_php7 [ /repo/ch03 ]#
值得注意的是,在 PHP 7 中,程序实际上无法继续:我们从未看到最后一行的输出。这是因为,尽管被掩盖了,但还是产生了一个致命错误,导致程序失败。而在 PHP 8 中,致命错误没有被掩盖,如图所示:
root@php8_tips_php8 [ /repo/ch03 ]# php8 php8_at_silencer.php
PHP Fatal error: bad in /repo/ch03/php8_at_silencer.php on
line 5
现在让我们看看 PHP 8 中有关 @
操作符的另一个不同之处。
@ 运算符和 error_reporting()
error_reporting()
函数通常用于覆盖 php.ini
文件中设置的 error_reporting
指令。然而,该函数的另一个用途是返回最新的错误代码。然而,在 PHP 8 之前的 PHP 版本中存在一个奇怪的例外情况,即如果使用了 @
操作符,error_reporting()
返回值为 0
。
在下面的代码示例中,我们定义了一个错误处理程序,当调用该程序时,它会报告收到的错误编号和字符串。此外,我们还会显示 error_reporting()
返回的值:
// /repo/ch03/php8_at_silencer_err_rep.php
function handler(int $errno , string $errstr) {
$report = error_reporting();
echo 'Error Reporting : ' . $report . "\n";
echo 'Error Number : ' . $errno . "\n";
echo 'Error String : ' . $errstr . "\n";
if (error_reporting() == 0) {
echo "IF statement works!\n";
}
}
与之前一样,我们定义了一个故意触发错误的 bad()
函数,然后使用 @
操作符调用该函数,如下所示:
function bad() {
trigger_error('We Be Bad', E_USER_ERROR);
}
set_error_handler('handler');
echo @bad();
在 PHP 7 中,error_reporting()
返回 0
,因此输出中会出现 IF
statement works!
root@root@php8_tips_php7 [ /repo/ch03 ] #
php php8_at_silencer_err_rep.php
Error Reporting : 0
Error Number : 256
Error String : We Be Bad
IF statement works!
而在 PHP 8 中运行时,error_reporting()
返回最后一个错误的值—本例中是 4437。当然,if()
表达式也失败了,没有额外的输出。下面是相同代码在 PHP 8 中运行的结果:
root@php8_tips_php8 [ /repo/ch03 ] #
php php8_at_silencer_err_rep.php
Error Reporting : 4437
Error Number : 256
Error String : We Be Bad
PHP 8 中 @
运算符使用差异的考虑到此结束。
最佳实践:不要使用 |