例如,我们希望通过捕获异常来处理除数为 0
的情况,但是在捕获到异常之前,PHP 就触发了错误。
<?php try { $a = 5 / 0; } catch (Exception $e) { $e->getMessage(); $a = -1; // 通过异常来处理 $a 为 0 的情况,但是实际上,捕获不到该异常 } echo $a; // PHP Warning: Division by zero
也就是说,PHP 将除数为 0 的情况当成了错误而触发,而不会自动抛出异常,因此没法捕获。类似的,在很多情况下,PHP 都没办法自动抛出异常。只能通过 if - else
语句判断再结合 throw
方法来并手动抛出异常。
上述情况的发生,主要还是因为异常机制是 PHP 向面向对象演进后得到的产物。而在此之前 PHP 的报错主要还是通过错误机制,因此,在很多情况下,PHP 的错误要比异常更有价值。不过 PHP 7 开始统一这两者,使错误也可以像异常那样抛出(这部分内容将放在异常部分讲解)。
PHP 中的错误可理解为 使脚本不运行不正常的情况,根据错误级别从高到低可划分为 5 类
Parse error
或 Syntax Error
- 语法解析错误,触发该错误后,脚本完全无法运行;Fatal Error
- 致命错误,触发该错误后,后面的脚本无法继续执行;Warning Error
- 出现比较不恰当的地方,脚本可继续执行;Notice Error
- 出现不恰当的地方,但是程度比 Warning Error
低,脚本可继续执行;Deprecated Error
- 不推荐这么使用,未来可能会废弃,脚本可继续执行;默认情况下,PHP 触发错误,并显示错误的级别及对应的提示。
Parse Error
示例 - 语句结尾不写分号
<?php echo "abc" // PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';
Fatal Error
示例 - 使用不存在的函数
<?php echo "before\n"; foo(); echo "after"; // 本行无法继续执行 // before // PHP Fatal error: Uncaught Error: Call to undefined function foo()
Warning Error
示例 - 引入不存在的文件
<?php $a = "foo"; include('bar.php'); echo $a; // 程序继续执行 // PHP Warning: include(bar.php): failed to open stream: No such file or directory ... // foo
Notice Error
示例 - 输出不存在的变量
<?php echo $foo; echo 12345; // PHP Notice: Undefined variable: foo // 12345
Deprecated Error
示例 - 在一些字符串函数中传入数字而非字符串
<?php strpos('12345', 3); // PHP Deprecated: strpos(): Non-string needles will be interpreted as strings in the future
除了默认触发消息外,用户也可以使用 set_error_handler
函数自定义错误处理,大多数错误类型都可以进行自定义处理,除了 E_ERROR
、 E_PARSE
、 E_CORE_ERROR
、 E_CORE_WARNING
、 E_COMPILE_ERROR
、 E_COMPILE_WARNING
外。
<?php set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] ) : mixed
<?php // E_ALL - 处理全部错误类型 set_error_handler('customError', E_ALL); /** * @param int $errno 错误的级别 * @param string $errstr 错误的信息 * @param string $errfile 错误的文件名(可选) * @param string $errline 错误发生的行号(可选) */ function customError(int $errno, string $errstr, string $errfile, string $errline) { echo sprintf('错误消息为 %s', $errstr); } $a = 5 / 0; // 错误消息为 Division by zero
用户也可以通过 trigger_error
函数来手动触发一个用户级别的错误(E_USER_ERROR
、E_USER_WARNING
、E_USER_NOTICE
、E_USER_DEPRECATED
)。
<?php function division($a, $b) { if($b == 0){ @trigger_error("0 不能作为除数", E_USER_NOTICE); return -1; } return $a / $b; } echo division(10, 0);
一些错误处理相关的常用配置
error_reporting
- 设置错误的报告级别display_errors
- 是否显示错误display_startup_error
- 是否显示 PHP 启动过程中的显示log_errors
- 设置是否将脚本运行的错误信息记录到服务器错误日志或者 error_log 之中《Modern PHP》提出了四个规则:
display_errors = On display_startup_error = On error_reporting = -1 log_errors = On
display_errors = Off display_startup_error = Off ; 报告 Notice 以外的所有错误 error_reporting = E_ALL & ~E_NOTICE log_errors = On
异常和错误消息字符串必须使用 sprintf
来进行拼接;
<?php throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
当错误类型为 E_USER_DEPRECATED
时,需要添加 @
<?php @trigger_error("foo", E_USER_DEPRECATED);