Php 简明教程

PHP Try…Catch

在 PHP 中,提供了关键字 try, catch, throwfinally 来处理异常。如果错误是程序自身无法处理的意外程序结果,则必须使用 die() 终止程序或设置自定义错误处理程序。

In PHP, the keywords try, catch, throw and finally are provided to deal with exceptions. Whereas an Error is an unexpected program result, which cannot be handled by the program itself and the program has to be terminated with die() or setting a custom error handler.

另一方面,异常是指可以通过某种方式处理的意外情况,在异常从正常流中抛出后,程序可以继续运行。

On the other hand, an exception refers to an unexpected situation which can be handled in such a way that the program may keep running after throwing the exception out of its normal flow.

可以通过 PHP 代码中的 catch 关键字抛出异常,并使用该关键字捕获异常。可能容易出现异常的代码块被 try 块包围。每个 try 至少必须有一个对应的 catch 或 finally 块。

An exception can be thrown, and caught with the catch keyword within PHP code. A code block which is potentially prone to exception is surrounded by a try block. Each try must have at least one corresponding catch or finally block.

Try, Throw, Catch, and Finally

与异常相关的四个关键字具有以下作用 −

The four exception related keywords have the following role to play −

  1. Try − A block of code where some exception is likely to occur is placed in "try" block. If exception is not triggered, the code continues execution. However, if exception does occur, it is "thrown". The execution is halted and PHP looks for matching "catch" block. If the exception is not caught, PHP issues a Fatal Error.

  2. Throw − Here is how you trigger an exception. Each "throw" must have at least one "catch" or "finally" block.

  3. Catch − a block that retrieves an exception and creates an object containing the exception information. Multiple catch blocks can be used to catch different exceptions.

  4. Finally − Code within a finally block is always executed after throw or catch block.

Example

以下是一个异常处理技术的示例。该代码在浏览器上渲染两个文本字段,并要求用户输入两个数字以执行它们的除法。如果第二个数字(分母)为 0,则会抛出异常,程序进入 catch 块并打印异常消息。否则,将显示除法的结果。

Here is an example of exception handling technique. The code renders two text fields on the browser and asks the user to enter two numbers for their division to be performed. If the second number (denominator) is 0, an exception is thrown and the program enters the catch block and prints the exception message. Otherwise the result of division is displayed.

<html>
<body>
   <form action="<?php echo $_SERVER['PHP_SELF'];?>" method="post">
      <h3>First No: <input type="text" name="first"/></h3>
      <h3>Second No: <input type="text" name="second"/></h3>
      <input type="submit" value="Submit" />
   </form>

   <?php
      if ($_SERVER["REQUEST_METHOD"] == "POST") {
         $x = $_POST['first'];
         $y = $_POST['second'];
         echo "$x $y";
         try {
            if ($y == 0) {
               throw new Exception("Division by Zero");
            }
            $z = $x/$y;
            echo "<h3>x = $x y = $y Division = $z<br>";
         }
         catch (Exception $e) {
            echo "<h3> Exception: " . $e->getMessage();
         }
      }
   ?>
</body>
</html>

它将生成以下 output

It will produce the following output

Case 1: x = 10 y = 5 Division = 2

Case 2: x = 10 y = 0
Exception: Division by Zero

The Exception Class

PHP 抛出一个 Exception class 对象。在 PHP 中,Exception 类是用户异常的基础。它实现可抛出的接口。

PHP throws an object of Exception class. In PHP, Exception class is the base for user exceptions. It implements throwable interface.

该类定义以下方法 −

This class defines the following methods −

getMessage()

此函数将异常消息作为字符串返回 −

This function returns the Exception message as a string −

final public Exception::getMessage(): string

getCode()

此函数返回异常代码作为 Exception 中的 int

This function returns the exception code as int in Exception −

final public Exception::getCode(): int

看看以下 example

Take a look at the following example

try {
   throw new Exception("Some error message", 30);
}
catch(Exception $e) {
   echo "The exception code is: " . $e->getCode();
}

getFile()

此函数返回创建异常的文件名

This function returns the filename in which the exception was created −

final public Exception::getFile(): string

看看以下 example

Take a look at the following example

try {
   if ($y == 0) {
      throw new Exception("Division by Zero");
   }
   $z = $x/$y;
   echo "<h3>x = $x y = $y Division = $z<br>";
}
catch (Exception $e) {
   echo "<h3> Exception: " . $e->getMessage(). " in " . $e->getFile();
}

它将生成以下 output

It will produce the following output

Exception: Division by Zero in C:\xampp\htdocs\hello.php

getLine()

此函数返回创建异常的行号

This function returns the line number where the exception was created −

final public Exception::getLine(): int

Example

请看以下示例:

Take a look at the following example −

<?php
   if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $x = $_POST['first'];
      $y = $_POST['second'];
      echo "$x $y";
      try {
         if ($y == 0) {
            throw new Exception("Division by Zero");
         }
         $z = $x/$y;
         echo "<h3>x = $x y = $y Division = $z<br>";
      }
      catch (Exception $e) {
         echo "<h3> Exception: " . $e->getMessage(). " in " . $e->getLine() . " of " . $e->getFile();
      }
   }
?>

它将生成以下 output

It will produce the following output

Exception: Division by Zero in 21 of C:\xampp\htdocs\hello.php

Multiple Catch Blocks

PHP 允许一系列 catch 块跟随 try 块来处理不同的异常情况。可以采用多个 catch 块来处理预定义的异常和错误,以及用户定义的异常。

PHP allows a series of catch blocks following a try block to handle different exception cases. Multiple catch blocks may be employed to handle predefined exceptions and errors as well as user defined exceptions.

Example

以下示例使用 catch 块来处理 DivisioByZeroError、TypeError、ArgumentCountError 和 InvalidArgumentException 条件。还有一个 catch 块来处理常规的 Exception。

The following example uses catch blocks to process DivisioByZeroError, TypeError, ArgumentCountError and InvalidArgumentException conditions. There is also a catch block to handle general Exception.

<?php
   declare(strict_types=1);
   function divide(int $a, int $b) : int {
      return $a / $b;
   }
   $a=10;
   $b=0;
   try {
   if (!$b) {
      throw new DivisionByZeroError('Division by zero.');
      if (is_int($a)==FALSE || is_int($b)==FALSE)
      throw new InvalidArgumentException("Invalid type of arguments");
      $result=divide($a, $b);
      echo $result;
   }

   // if argument types not matching
   catch (TypeError $x) {
      echo $x->getMessage();
   }

   // if denominator is 0
   catch (DivisionByZeroError $y) {
      echo $y->getMessage();
   }

   // if number of arguments not equal to 2
   catch (ArgumentCountError $z) {
      echo $z->getMessage();
   }

   // if argument types not matching
   catch (InvalidArgumentException $i) {
      echo $i->getMessage();
   }

   // any uncaught exception
   catch (Exception $ex) {
      echo $ex->getMessage();
   }
?>

首先,由于分母为 0,因此将显示“除以 0”错误 −

To begin with, since denominator is 0, "divide by 0" error will be displayed −

Division by 0

设置 $b=3 ,它将导致 TypeError,因为期望除数函数返回整数,但是除法结果为 float

Set $b=3 which will cause TypeError because divide function is expected to return integer but division results in float.

divide(): Return value must be of type int, float returned

如果仅将一个变量传递给除数函数,通过更改 $res=divide($a); ,这将导致 ArgumentCountError

If just one variable is passed to divide function by changing $res=divide($a); this will result in an ArgumentCountError

Too few arguments to function divide(), 1 passed in C:\xampp\htdocs\hello.php on line 16 and exactly 2 expected

如果其中一个参数不是整数,则是 InvalidArgumentException 的情况。将 $b 更改为字符串 −

If one of arguments is not integer, it is a case of InvalidArgumentException. Change $b to a string −

Invalid type of arguments

The Finally Block

finally 块也可能在 catch 块后面或代替 catch 块指定。无论是否抛出异常, finally 块内的代码都将在 trycatch 块之后始终执行,并且在恢复正常执行之前执行。

A finally block may also be specified after or instead of catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.

try {
   if ($y == 0) {
      throw new Exception("Division by Zero");
   }
   $z = $x/$y;
   echo "<h3>x = $x y = $y Division = $z </h3><br>";
}
catch (Exception $e) {
   echo "<h3> Exception: " . $e->getMessage(). "</h3>";
}
finally {
   echo "<h3>End of try - catch - finally</h3>";
}

它将生成如下输出:

It will produce the following output −

Case 1 −

Case 1 −

x = 10 y = 5 Division = 2
End of try - catch – finally

Case 2 −

Case 2 −

X=10 y=0
Exception: Division by Zero
End of try - catch – finally

Finally With Return

try 块或 catch 块(或两者)包含 return 语句时,有 finally 块的特殊行为。通常, return 语句会导致程序控制权返回到调用位置。但是,对于具有 return 的 try/catch 块的函数, finally 块中的语句将在返回之前首先执行。

There is a peculiar behaviour of finally block when either try block or catch block (or both) contain a return statement. Normally a return statement causes the control of program to go back to the calling position. However, in case of a function with try/catch block with return, the statements in finally block are executed first before returning.

Example

在以下示例中,div() 函数有一个“try-catch-finally”构造。没有异常的 try 块返回除法结果。如果发生异常,则 catch 块返回错误消息。但是,无论哪种情况, finally 块中的语句都将首先执行。

In the following example, the div() function has a "try-catch-finally" construct. The try block without exception returns result of division. In case of exception, the catch block returns an error message. However, in either case, the statement in the finally block is executed first.

<?php
   function div($x, $y) {
      try {
         if ($y==0)
         throw new Exception("Division by 0");
         else
         $res=$x/$y;;
         return $res;
      }
      catch (Exception $e) {
         return $e->getMessage();
      }
      finally {
         echo "This block is always executed\n";
      }
   }
   $x=10;
   $y=0;
   echo div($x,$y);
?>

它将生成以下 output

It will produce the following output

This block is always executed
Division by 0