如果你要为PHP编写自己的错误处理程序,有几条规则是你绝对必须遵守的。否则,它可能会使其他库和应用程序的行为崩溃,这些库和应用程序并不期望在错误处理程序中出现背叛。
参数
处理程序的签名看起来像这样。
function errorHandler(
int $severity,
string $message,
string $file,
int $line,
array $context = null // pouze v PHP < 8
): ?bool {
...
}
$severity 参数包含错误级别(E_NOTICE,E_WARNING, ...)。致命的错误,如E_ERROR ,不能用处理程序来捕捉,所以参数将永远不会有这些值。幸运的是,致命的错误基本上已经从 PHP 中消失了,取而代之的是异常。
$message 参数是一个错误信息。如果html_errors 指令被启用,特殊字符如< 等会被写成 HTML 实体,所以你必须把它们解码成纯文本。 但是,要注意有些字符不会被写成实体,这是一个错误。 这使得在纯文本中实际显示的错误容易受到 XSS 的攻击。
参数$file 和$line 代表文件名和发生错误的行。如果错误发生在eval() ,$file ,将被附加上这个信息。
最后,$context 参数包含了一个局部变量的数组,这对调试是很有用的信息,但从 PHP 8 开始已经废弃了。如果处理程序要在 PHP 8 中工作,请省略该参数或给它一个默认值。
返回值
处理程序的返回值可以是null 或false 。
值false ,说明标准的PHP处理程序仍将被调用。根据PHP的配置,它可能会输出错误,记录它,等等,它也会让错误_get_last()函数可用。
抑制的错误
在PHP中,可以通过使用关闭操作符@ 或使用error_reporting() 来抑制错误的显示。
// potlač chyby úrovně E_USER_DEPRECATED
error_reporting(~E_USER_DEPRECATED);
// potlač všechny chyby při volání fopen()
$file = @fopen($name, 'r');
即使有错误抑制**,处理程序也会被调用**。因此,我们首先需要检查错误是否被抑制,如果被抑制,我们需要停止处理。
if (($severity & error_reporting()) !== $severity) {
return false;
}
在这种情况下,我们必须使用return false 终止处理,这样,标准错误处理程序仍然被触发。这不会打印和记录任何东西(因为错误被抑制了),但将确保可以用error_get_last() 。
其他错误
如果错误处理程序处理了错误(如打印自己的信息等),就不需要调用标准错误处理程序。这样就不可能用error_get_last() ,但这在实践中并不重要,因为这个功能主要是与关闭操作符结合使用。
另一方面,如果处理程序不处理这个错误,它应该返回false ,这样就不会隐藏它。