了解 PHP 8 错误处理

一直以来,许多 PHP 错误条件的错误级别远远低于其实际严重程度。这给了开发人员一种虚假的安全感,因为只看到一个 "通知" 会让他们认为自己的代码没有缺陷。许多情况以前只生成通知或警告,而实际上它们的严重性值得更多关注。

在本节中,我们将介绍 PHP 8 中的一些错误处理增强功能,这些功能将继续保持良好的编码实践的整体趋势。本章的讨论将帮助您重新审视自己的代码,从而提高效率,减少维护问题。

在接下来的几个小节中,我们将介绍可能对代码产生影响的某些 "通知" 和 "警告" 错误条件的变化。首先让我们看看 PHP 8 在处理未定义变量方面的变化。

未定义变量处理

PHP 的一个臭名昭著的特点是它如何处理 未定义的变量。请看这个简单的代码块。注意 $a$b 变量尚未定义:

// /repo/ch03/php8_undef_var.php
$c = $a + $b;
var_dump($c);

在 PHP 7 下运行,输出结果如下:

PHP Notice: Undefined variable: a in
/repo/ch03/php7_undef_var.php on line 3
PHP Notice: Undefined variable: b in /repo/ch03/php7_undef_
var.php on line 3
int(0)

从输出中可以看到,PHP 7 发出了通知,让我们知道我们使用了未定义的变量。如果我们使用 PHP 8 运行完全相同的代码,很快就会发现以前的 "通知" 已经变成了 "警告",如图所示:

PHP Warning: Undefined variable $a in /repo/ch03/php8_undef_
var.php on line 3
PHP Warning: Undefined variable $b in /repo/ch03/php8_undef_
var.php on line 3
int(0)

PHP 8 中错误级别提升的原因是,许多开发人员认为使用未定义变量是一种无害的做法,但这种做法实际上是 相当危险的!为什么?答案是,PHP 会在没有明确指示的情况下,默默地为任何未定义变量赋值 NULL。实际上,你的程序依赖的是 PHP 的默认行为,而这种默认行为可能会在语言的未来升级中发生改变。

在本章接下来的几节中,我们将介绍其他错误级别的升级。但请注意,将通知升级为警告并不会影响代码的运行。不过,它可能会让你注意到更多潜在的问题,如果是这样的话,它的作用是生成更好的代码。与未定义变量不同的是,未定义常量的错误现在被进一步升级,你将在下一小节中看到。

未定义常量处理

在 PHP 8 下运行时,对 未定义常量 的处理方式有所改变。不过,在本例中,以前的警告(Warning)在 PHP 8 中变成了错误(Error)。请看一下这个看起来无害的代码块:

// /repo/ch03/php7_undef_const.php
echo PHP_OS . "\n";
echo UNDEFINED_CONSTANT . "\n";
echo "Program Continues ... \n";

第一行回传一个 PHP_OS 预定义常量,用于识别操作系统。在 PHP 7 中,会生成一个 "通知";但最后一行输出的是 Program Continues …​ ,如图所示:

PHP Notice: Use of undefined constant UNDEFINED_CONSTANT -
assumed 'UNDEFINED_CONSTANT' in /repo/ch03/php7_undef_const.php
on line 6
Program Continues ...

同样的代码现在在 PHP 8 中运行时会产生致命错误,如图所示:

PHP Fatal error: Uncaught Error: Undefined constant
"UNDEFINED_CONSTANT" in /repo/ch03/php8_undef_const.php:6

因此,任何没有在使用前定义常量的糟糕代码都会在 PHP 8 中崩溃和烧毁!一个好习惯是在程序代码开始时为所有变量分配一个默认值。如果计划使用常量,最好尽快定义它们,而且最好在一个地方定义。

一种方法是在包含的文件中定义所有常量。如果是这种情况,请确保任何使用这些常量的程序脚本都已加载了包含常量定义的文件。

最佳实践:在使用前,在程序代码的开头为所有变量分配默认值。在使用任何自定义常量之前,请务必对其进行定义。如果是这种情况,请确保使用这些常量的程序脚本已加载包含常量定义的文件。

错误级别默认值

值得注意的是,PHP 8 更新了分配给 php.ini 文件 error_reporting 指令的默认错误级别。 在 PHP 7 中,默认 error_reporting 级别如下:

error_reporting=E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED

在 PHP 8 中,新级别要简单得多,如下所示:

error_reporting=E_ALL

值得注意的是,php.ini 文件中的 display_startup_errors 设置现在默认为启用。这对生产服务器来说可能是个问题,因为你的网站可能会在 PHP 启动时无意中显示错误信息。

本节的主要内容是:过去,PHP 只允许通过发布通知或警告来逃避某些不良行为。然而,正如本节所述,不解决产生警告或通知背后的问题的危险在于 PHP 会默默地代表你采取一些行动。不依赖 PHP 代您做出决定会减少隐藏的逻辑错误。遵循良好的编码规范(如在使用所有变量前为其指定默认值)有助于避免此类错误。现在,让我们仔细看看在 PHP 8 中警告已升级为错误。