您的位置 首页 php

PHP 核心特性 – 错误处理(life)

错误与异常

错误,可以理解 程序本身的错误 ,例如语法错误。而异常则更偏向于 程序运行不符合预期 或者 不符合正常流程 ;对于 PHP 语言而言,处理错误和处理异常使用的机制完全不同,因此很容易让人产生困惑。

例如,我们希望通过捕获异常来处理除数为 0 的情况,但是在捕获到异常之前,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 的错误要比异常更有价值。不过 PHP7 开始统一这两者,使错误也可以像异常那样抛出(这部分内容将放在异常部分讲解)。

错误级别

PHP 中的错误可理解为 使脚本不运行不正常的情况 ,根据错误级别从高到低可划分为五类

  1. Parse error 或 Syntax Error – 语法解析错误,触发该错误后,脚本 完全 无法运行;
  2. Fatal Error – 致命错误,触发该错误后, 后面的脚本 无法继续执行;
  3. Warning Error – 出现比较不恰当的地方,脚本可 继续执行
  4. Notice Error – 出现不恰当的地方,但是程度比 Warning Error 低,脚本可 继续执行
  5. Deprecated Error – 不推荐这么使用,未来可能会废弃,脚本可 继续执行

默认情况下,PHP 触发错误,并显示错误的级别及对应的提示。

Parse Error 示例 – 语句结尾不写分号

 echo "abc"
// PHP Parse error:  syntax error, unexpected end of file, expecting ',' or ';  

Fatal Error 示例 – 使用不存在的函数

 echo "before\n";
foo();
echo "after"; // 本行无法继续执行
// before
// PHP Fatal error:  Uncaught Error: Call to undefined function foo()  

Warning Error 示例 – 引入不存在的文件

 $a = "foo";
include('bar.php');
echo $a; // 程序继续执行
// PHP Warning:  include(bar.php): failed to open stream: No such file or directory ...
// foo  

Notice Error 示例 – 输出不存在的变量

 echo $foo;
echo 12345;
// PHP Notice:  Undefined variable: foo
// 12345  

Deprecated Error 示例 – 在一些字符串函数中传入数字而非字符串

 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 外。

 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)。

 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》提出了四个规则

  1. 一定要让 PHP 报告错误;
  2. 在开发环境中要显示错误;
  3. 在生产环境中不能显示错误;
  4. 在开发环境和生产环境中都要记录错误;

开发环境推荐配置

 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  

Symfony 编码规范相关

异常和错误消息字符串必须使用 sprintf 来进行拼接;

 throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name));  

当错误类型为 E_USER_DEPRECATED 时,需要添加 @

 @trigger_error("foo", E_USER_DEPRECATED);  

参考资料

  • PHP Errors: 4 Different Types (Warning, Parse, Fatal, and Notice Error)
  • PHP: 预定义常量 – Manual
  • PHP 核心技术与最佳实践 (豆瓣)
  • PHP: 运行时配置 – Manual
  • PHP 规范 – Symfony 代码规范 | PHP 技术论坛

文章来源:智云一二三科技

文章标题:PHP 核心特性 – 错误处理(life)

文章地址:https://www.zhihuclub.com/77834.shtml

关于作者: 智云科技

热门文章

网站地图