PHP - 错误处理



PHP 中的错误处理是指在 PHP 代码中设置机制,以有效地识别和恢复程序可能遇到的运行时错误。在 PHP 中,错误处理借助于:

  • die() 函数

  • 错误处理函数

die() 函数

die() 函数是 PHP 中 exit() 的别名。两者都会在遇到时终止当前 PHP 脚本的执行。如果在括号中指定一个可选字符串,则该字符串将在程序终止之前输出。

die("message");

示例

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

<?php
   if(!file_exists("nosuchfile.txt")) {
      die("File not found");
   } else {
      $file = fopen("nosuchfile","r");
      print "Opend file sucessfully";
	  
      // Rest of the code here.
      fclose($file);
   }
?>

它将产生以下输出

File not found

使用上述技术,您可以随时停止程序错误并显示更有意义且用户友好的消息,而不是让 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 是与预定义错误级别相对应的整数。

序号 常量和描述
1

E_ERROR (int)

无法恢复的致命运行时错误。脚本执行将停止。

1
2

E_WARNING (int)

运行时警告(非致命错误)。脚本执行不会停止。

2
3

E_PARSE (int)

编译时解析错误。解析错误应该只由解析器生成。

4
4

E_NOTICE (int)

运行时通知。可能表示错误,但也可能在脚本正常运行过程中发生。

8
5

E_CORE_ERROR (int)

在 PHP 初始启动期间发生的致命错误。这类似于E_ERROR

16
6

E_CORE_WARNING (int)

在 PHP 初始启动期间发生的警告(非致命错误)。这类似于E_WARNING

32
7

E_COMPILE_ERROR (int)

致命的编译时错误。这类似于E_ERROR

64
8

E_COMPILE_WARNING (int)

编译时警告(非致命错误)。这类似于E_WARNING

128
9

E_USER_ERROR (int)

用户生成的错误消息。这类似于E_ERROR,由使用 PHP 函数 trigger_error() 生成的 PHP 代码生成。

256
10

E_USER_WARNING (int)

用户生成的警告消息。这类似于E_WARNING,由使用 trigger_error() 函数生成的 PHP 代码生成。

512
11

E_USER_NOTICE (int)

用户生成的通知消息。这类似于由使用 trigger_error() 函数生成的 PHP 代码生成的E_NOTICE

1024
12

E_STRICT (int)

启用此选项后,PHP 将建议对您的代码进行更改,以确保代码的最佳互操作性和前向兼容性。

2048
13

E_RECOVERABLE_ERROR (int)

可捕获的致命错误。如果用户定义的处理程序未捕获该错误,则应用程序将像E_ERROR一样中止。

4096
14

E_DEPRECATED (int)

运行时通知。启用此选项可接收有关将来版本中无效代码的警告。

8192
15

E_USER_DEPRECATED (int)

用户生成的警告消息。这类似于由使用 trigger_error() 函数生成的 PHP 代码生成的E_DEPRECATED

16384
16

E_ALL (int)

所有错误、警告和通知。

32767

示例

请查看以下示例:

<?php
   error_reporting(E_ERROR);

   function myerrorhandler($errno, $errstr) {
      echo "error No: $errno Error message: $errstr" . PHP_EOL;
      echo "Terminating PHP script"; 
      die();
   }

   set_error_handler("myerrorhandler");

   $f = fopen("nosuchfile.txt", "r");
   echo "file opened successfully";
   // rest of the code
   fclose($f);
?>

它将产生以下输出

error No: 2 Error message: fopen(nosuchfile.txt): Failed to open stream: No 
such file or directory
Terminating PHP script

PHP 的错误类层次结构从 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 中抛出异常并捕获(“catch”)异常。代码可以用 try 块包围。

  • 每个 try 必须至少有一个对应的 catch 块。可以使用多个 catch 块来捕获不同类别的异常。

  • 可以在 catch 块中抛出(或重新抛出)异常。

示例

下面是一段代码,请复制并粘贴这段代码到一个文件中并验证结果。

<?php
   try {
      $error = 'Always throw this error';
      throw new Exception($error);
      
      // Code following an exception is not executed.
      echo 'Never executed';
   }catch (Exception $e) {
      echo 'Caught exception: ',  $e->getMessage(), "";
   }
   
   // Continue execution
   echo 'Hello World';
?>

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

  • getMessage() − 异常信息

  • getCode() − 异常代码

  • getFile() − 源文件名

  • getLine() − 源代码行号

  • getTrace() − backtrace() 的数组

  • getTraceAsString() − 格式化的跟踪字符串

创建自定义异常处理程序

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

string set_exception_handler ( callback $exception_handler )

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

示例

请查看以下示例:

<?php
   function exception_handler($exception) {
      echo "Uncaught exception: " , $exception->getMessage(), "\n";
   }
	
   set_exception_handler('exception_handler');
   throw new Exception('Uncaught Exception');
   
   echo "Not Executed";
?>

查看完整的错误处理函数集,请访问 PHP 错误处理函数

广告