错误,能够理解程序自己的错误,例如语法错误。而异常则更偏向于程序运行不符合预期或者不符合正常流程;对于 PHP 语言而言,处理错误和处理异常使用的机制彻底不一样,所以很容易让人产生困惑。php
例如,咱们但愿经过捕获异常来处理除数为 0 的状况,可是在捕获到异常以前,PHP 就触发了错误。laravel
1 try { 2 $a = 5 / 0; 3 } catch (Exception $e) { 4 $e->getMessage(); 5 $a = -1; // 经过异常来处理 $a 为 0 的状况,可是实际上,捕获不到该异常 6 } 7 8 echo $a; 9 // PHP Warning: Division by zero
也就是说,PHP 将除数为 0 的状况当成了错误而触发,而不会自动抛出异常,所以无法捕获。相似的,在不少状况下,PHP 都没办法自动抛出异常。只能经过 if - else
语句判断再结合 throw
方法来并手动抛出异常。sql
上述状况的发生,主要仍是由于异常机制是 PHP 向面向对象演进后获得的产物。而在此以前 PHP 的报错主要仍是经过错误机制,所以,在不少状况下,PHP 的错误要比异常更有价值。不过 PHP7 开始统一这二者,使错误也能够像异常那样抛出(这部份内容将放在异常部分讲解)。shell
PHP 中的错误可理解为 使脚本不运行不正常的状况,根据错误级别从高到低可划分为五类服务器
默认状况下,PHP 触发错误,并显示错误的级别及对应的提示。架构
Parse Error 示例 - 语句结尾不写分号并发
1 echo "abc" 2 // PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';
Fatal Error 示例 - 使用不存在的函数分布式
1 echo "before\n"; 2 foo(); 3 echo "after"; // 本行没法继续执行 4 // before 5 // PHP Fatal error: Uncaught Error: Call to undefined function foo()
Warning Error 示例 - 引入不存在的文件函数
1 $a = "foo"; 2 include('bar.php'); 3 echo $a; // 程序继续执行 4 // PHP Warning: include(bar.php): failed to open stream: No such file or directory ... 5 // foo 6 Notice Error 示例 - 输出不存在的变量 7 8 echo $foo; 9 echo 12345; 10 // PHP Notice: Undefined variable: foo 11 // 12345
Deprecated Error 示例 - 在一些字符串函数中传入数字而非字符串微服务
1 strpos('12345', 3); 2 // 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
外。
1 set_error_handler ( callable $error_handler [, int $error_types = E_ALL | E_STRICT ] ) : mixed
示例
1 <?php 2 // E_ALL - 处理所有错误类型 3 set_error_handler('customError', E_ALL); 4 5 /** 6 * @param int $errno 错误的级别 7 * @param string $errstr 错误的信息 8 * @param string $errfile 错误的文件名(可选) 9 * @param string $errline 错误发生的行号(可选) 10 */ 11 function customError(int $errno, string $errstr, string $errfile, string $errline) 12 { 13 echo sprintf('错误消息为 %s', $errstr); 14 } 15 16 $a = 5 / 0; // 错误消息为 Division by zero
用户也能够经过 trigger_error
函数来手动触发一个用户级别的错误(E_USER_ERROR
、E_USER_WARNING
、E_USER_NOTICE
、E_USER_DEPRECATED
)。
1 function division($a, $b) { 2 if($b == 0){ 3 @trigger_error("0 不能做为除数", E_USER_NOTICE); 4 return -1; 5 } 6 return $a / $b; 7 } 8 9 echo division(10, 0);
一些错误处理相关的经常使用配置
error_reporting
- 设置错误的报告级别display_errors
- 是否显示错误display_startup_error
- 是否显示 PHP 启动过程当中的显示log_errors
- 设置是否将脚本运行的错误信息记录到服务器错误日志或者 error_log 之中《Modern PHP》提出了四个规则
开发环境推荐配置
1 display_errors = On 2 display_startup_error = On 3 error_reporting = -1 4 log_errors = On
生产环境推荐配置
1 display_errors = Off 2 display_startup_error = Off 3 ; 报告 Notice 之外的全部错误 4 error_reporting = E_ALL & ~E_NOTICE 5 log_errors = On 6
异常和错误消息字符串必须使用 sprintf
来进行拼接;
throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));
当错误类型为 E_USER_DEPRECATED
时,须要添加 @
@trigger_error("foo", E_USER_DEPRECATED);
参考资料