如果你在PHP中编写自己的错误处理程序,绝对有必要遵循一些规则。否则,它可能会破坏其他库和应用程序的行为,而这些库和应用程序并不期望在错误处理程序中出现背叛行为。
参数
处理程序的签名看起来像这样。
function errorHandler(
int $severity,
string $message,
string $file,
int $line,
array $context = null // only in PHP < 8
): ?bool {
...
}
参数$severity 包含错误级别(E_NOTICE,E_WARNING, ...)。致命的错误,如E_ERROR ,不能被处理程序捕获,所以参数永远不会有这些值。幸运的是,致命的错误基本上已经从PHP中消失了,取而代之的是异常。
参数$message 是一个错误信息。如果html_errors指令被启用,特殊字符如< 等会被写成 HTML 实体,所以必须将其解码为纯文本。但是要注意,有些字符没有被编码为实体,这是个错误。在纯PHP中显示错误,所以很容易造成XSS。
参数$file 和$line 代表文件名和发生错误的行。如果错误发生在eval() ,$file ,将补充这些信息。
最后,参数$context 包含一个局部变量数组,这对调试很有用,但从 PHP 8 开始已经被放弃。为了与 PHP 8 兼容,可省略该参数或给它一个默认值。
返回值
处理程序的返回值可以是null 或false 。
值false 表示将调用一个标准的 PHP 处理程序。根据配置,它可以打印错误,记录错误,等等。它也会让error_get_last()函数得到它。
抑制的错误
在PHP中,错误可以通过使用shut-up操作符@ 或使用error_reporting() 来抑制(或静音)。
// suppress errors E_USER_DEPRECATED
error_reporting(~E_USER_DEPRECATED);
// suppress all errors when calling fopen()
$file = @fopen($name, 'r');
即使错误被压制,处理程序也会被调用。因此,首先需要检查错误是否被抑制,如果是的话,我们必须结束处理程序。
if (($severity & error_reporting()) !== $severity) {
return false;
}
在这种情况下,必须用return false终止处理程序,以运行一个标准错误处理程序。它不打印任何东西,也不记录(因为错误被抑制了),但它确保错误可以被error_get_last() 。
其他错误
如果处理程序处理了错误(例如,打印它自己的信息,等等),就不需要调用标准处理程序。尽管使用error_get_last() ,不可能得到错误,但这在实践中并不重要,因为这个函数主要是和关闭操作符一起使用。
另一方面,如果处理程序不处理错误,它应该返回false ,以便不隐藏它。