PHP - 错误处理


PHP 错误处理是指在 PHP 代码中进行配置,以有效地识别程序可能遇到的运行时错误并从中恢复。在 PHP 中,错误是借助 -

  • die() 函数
  • 错误处理程序函数

die() 函数

die() 函数是 PHP 中 exit() 的别名。遇到这两种情况时,都会导致当前 PHP 脚本终止。如果在括号中指定了可选字符串,则将在程序终止之前输出。


 die("message");

例子

以下代码是 die() 在 PHP 脚本中的典型用法。如果 PHP 找不到文件,则显示 “找不到文件” 消息,否则继续打开它进行后续处理。


<?php
   if(!file_exists("nosuchfile.txt")) {
      die("找不到文件");
   } else {
      $file = fopen("nosuchfile","r");
      print "已成功打开文件";
      
      // 其余的代码在这里。
      fclose($file);
   }
?>

它将产生以下输出 -

找不到文件

使用上述技术,您可以在程序出错时停止程序并显示更有意义和用户友好的消息,而不是让 PHP 生成致命错误消息。

错误处理程序函数

使用 die() 进行错误处理被认为是一种笨拙且糟糕的程序设计,因为它会给网站用户带来难看的体验。PHP 提供了一种更优雅的替代方案,您可以使用它来定义自定义函数并指定它来处理错误。

set_error_handler() 函数具有以下参数 -


set_error_handler(?callable $callback, int $error_levels = E_ALL): ?callable

第一个参数是用户定义的函数,每当遇到错误时都会自动调用该函数。

自定义错误处理程序回调函数应具有以下参数 -


handler(
   int $errno,
   string $errstr,
   string $errfile = ?,
   int $errline = ?,
   array $errcontext = ?
): bool

参数

参数 重要性 描述
errno 必填 指定用户定义错误的错误级别。 它必须是数值。
errstr 必填 指定用户定义错误的错误消息。
errfile 自选 指定发生错误的文件名。
errline 自选 指定发生错误的行号。
errcontext 自选 指定一个数组,其中包含发生错误时使用的变量及其值。

如果回调函数返回 false,则调用默认错误。

$errno 是对应于预定义错误级别的整数。

常量 描述
E_ERROR (int) 无法恢复的致命运行时错误。脚本的执行已停止。 1
E_WARNING (int) 运行时警告(非致命错误)。脚本的执行不会停止。 2
E_PARSE (int) 编译时分析错误。解析错误应仅由解析器生成。 4
E_NOTICE (int) 运行时通知。这可能表示错误,但也可能在运行脚本的正常过程中发生。 8
E_CORE_ERROR (int) PHP 初始启动期间发生的致命错误。这就像一个E_ERROR 16
E_CORE_WARNING (int) PHP 初始启动期间发生的警告(非致命错误)。这就像一个E_WARNING 32
E_COMPILE_ERROR (int) 致命的编译时错误。这就像一个E_ERROR 64
E_COMPILE_WARNING (int) 编译时警告(非致命错误)。这就像一个E_WARNING 128
E_USER_ERROR (int) 用户生成的错误消息。这类似于使用 PHP 函数 trigger_error() 在 PHP 代码中生成的E_ERROR 256
E_USER_WARNING (int) 用户生成的警告消息。这类似于 E_WARNING,使用函数 trigger_error() 在 PHP 代码中生成。 512
E_USER_NOTICE (int) 用户生成的通知消息。这类似于使用函数 trigger_error() 在 PHP 代码中生成的E_NOTICE 1024
E_STRICT (int) 启用此选项可让 PHP 建议对代码进行更改,这将确保代码的最佳互操作性和向前兼容性。 2048
E_RECOVERABLE_ERROR (int) 可捕获的致命错误。如果用户定义的处理程序未捕获错误,则应用程序将中止,因为它是一个E_ERROR 4096
E_DEPRECATED (int) 运行时通知。启用此选项可接收有关代码在将来版本中不起作用的警告。 8192
E_USER_DEPRECATED (int) 用户生成的警告消息。这类似于 E_DEPRECATED,使用函数 trigger_error() 在 PHP 代码中生成。 16384
E_ALL (int) 所有错误、警告和通知。 32767

例子

请看下面的例子 -


<?php
   error_reporting(E_ERROR);

   function myerrorhandler($errno, $errstr) {
      echo "错误编号: $errno 错误信息: $errstr" . PHP_EOL;
      echo "终止PHP脚本"; 
      die();
   }

   set_error_handler("myerrorhandler");

   $f = fopen("nosuchfile.txt", "r");
   echo "文件已成功打开";
   // 其余代码
   fclose($f);
?>

它将产生以下输出 -

错误编号: 2 错误信息: fopen(nosuchfile.txt): Failed to open stream: No 
such file or directory
终止PHP脚本

PHP 的 error 类层次结构从 throwable 接口开始。PHP 所有预定义的 Error 类都是从 Error 类继承的。

ArithmeticError 类

ArithmeticError 类继承自 Error 类。在执行某些数学运算(例如按负量执行按位移位运算)时,可能会发生此类错误。

例子

请看下面的例子 -


<?php
   try {
      $a = 10;
      $b = -3;
      $result = $a << $b;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   }
?>

将产生以下输出 -

Bit shift by negative number

当调用 intdiv() 函数导致 值 超出整数的合法边界时,也会引发此错误。

例子

请看下面的例子 -


<?php
   try {
      $a = PHP_INT_MIN;
      $b = -1;
      $result = intdiv($a, $b);
      echo $result;
   } 
   catch (ArithmeticError $e) {
      echo $e->getMessage(); 
   } 
?>

将产生以下输出 -

Division of PHP_INT_MIN by -1 is not an integer

DivisionByZeroError (除法零错误)

DivisionByZeroError 类是 ArithmeticError 类的子类。当除法运算中分母的值为零时,会出现这种类型的错误。

示例:以零取模

请看以下示例:


<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a%$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它将产生以下输出 -

Modulo by zero

模运算符 (%) 的第二个运算符为 0,而 intdiv() 函数的第二个参数为 0 时,也会发生这种情况。

示例:除以零

请看下面的例子 -


<?php
   try {
      $a = 10;
      $b = 0;
      $result = $a/$b;
      echo $result;
   } 
   catch (DivisionByZeroError $e) {
      echo $e->getMessage(); 
   }
?>

它将产生以下输出 -

Division by zero

ArgumentCountError

当传递给用户定义的函数或方法的参数小于其定义中的参数时,PHP 解析器会抛出 ArgumentCountError

例子

请看下面的例子 -


<?php
   function add($x, $y) {
      return $x+$y;
   }
   try {
      echo add(10);
   }
   catch (ArgumentCountError $e) {
      echo $e->getMessage();
   }
?>

它将产生以下输出 -

Too few arguments to function add(), 1 passed in C:\xampp\php\test.php on line 9 and exactly 2 expected

TypeError (类型错误)

当 实际参数类型 和 形式参数类型 不匹配时,会引发此错误,返回类型与声明的返回类型不匹配。

例子

请看下面的例子 -


<?php
   function add(int $first, int $second) {
      echo "addition: " . $first + second;
   }

   try {
      add('first', 'second');
   } 
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它将产生以下输出 -

add(): Argument #1 ($first) must be of type int, string given, 
   called in /home/cg/root/63814/main.php on line 7

当 PHP 内置函数传递的参数数量不正确时,也会引发 TypeError。但是,必须在开始时设置 “strict_types=1” 指令。

例子

请看下面的例子 -


<?php
   declare(strict_types=1);
   try {
      echo pow(100,2,3);
   }
   catch (TypeError $e) {
      echo $e->getMessage(), "";
   }
?>

它将产生以下输出 -

pow() expects exactly 2 parameters, 3 given

PHP 异常处理

PHP 具有与其他编程语言类似的异常模型。异常很重要,可以更好地控制错误处理。

让我们解释一下与异常相关的新关键字。

关键词 描述
Try  使用异常的函数应位于 “try” 块中。如果异常未触发,代码将照常继续。但是,如果触发了异常,则会“引发”异常。
Throw  这是触发异常的方式。每个 “throw” 必须至少有一个 “catch”。
Catch  catch” 块检索异常并创建包含异常信息的对象。

当抛出异常时,该语句后面的代码将不会被执行,PHP 将尝试找到第一个匹配的 catch 块。如果未捕获到异常,将发出 PHP 致命错误,并显示“未捕获的异常...

  • 在 PHP 中可以引发异常并捕获 (“catched”) 异常。代码可能括在 try 块中。
  • 每个 try 必须至少有一个相应的 catch 块。多个 catch 块可用于捕获不同类别的异常。
  • 可以在 catch 块中引发 (或重新引发) 异常。

例子

以下是一段代码,将此代码复制并粘贴到文件中并验证结果。


<?php
   try {
      $error = '总是抛出此错误';
      throw new Exception($error);
      
      // 异常后的代码不会执行。
      echo 'Never executed';
   }catch (Exception $e) {
      echo '捕获异常: ',  $e->getMessage(), "";
   }
   
   // 继续执行
   echo 'Hello World';
?>

在上面的例子中,$e->getMessage 函数用于获取错误消息。Exception 类中可以使用以下函数。

意义
getMessage()  异常消息
getCode() 异常代码
getFile() 源文件名
getLine() 源行
getTrace() backtrace() 的 n 数组
getTraceAsString() 格式化的跟踪字符串

创建自定义异常处理程序

您可以定义自己的自定义异常处理程序。使用以下函数设置用户定义的异常处理程序函数。


 string set_exception_handler ( callback $exception_handler )

此处 exception_handler 是发生未捕获的异常时要调用的函数的名称。此函数必须在调用 set_exception_handler() 之前定义。

例子

请看下面的例子 -


<?php
   function exception_handler($exception) {
      echo "未捕获的异常: " , $exception->getMessage(), "\n";
   }
    
   set_exception_handler('exception_handler');
   throw new Exception('Uncaught Exception');
   
   echo "未执行";
?>

在 PHP 错误处理函数 检查完整的错误处理函数集