PHP Try…Catch

Trong PHP, các từ khóa try, catch, throw finally được cung cấp để xử lý ngoại lệ. Trong khi đó, một Lỗi (Error) là kết quả chương trình không mong đợi, không thể được xử lý bởi chính chương trình và chương trình phải bị kết thúc bằng cách sử dụng die() hoặc thiết lập một bộ xử lý lỗi tùy chỉnh.

Mặt khác, một ngoại lệ đề cập đến một tình huống không mong đợi có thể được xử lý theo cách mà chương trình vẫn có thể tiếp tục chạy sau khi ném ngoại lệ ra khỏi dòng chảy bình thường của nó.

Một ngoại lệ có thể được ném ra và được bắt với từ khóa catch trong mã PHP. Một khối mã có khả năng xảy ra ngoại lệ được bao quanh bởi một khối try . Mỗi try phải có ít nhất một khối catch hoặc finally tương ứng.

Try, Throw, Catch, and Finally

Bốn từ khóa liên quan đến ngoại lệ có vai trò như sau −

  • Try − Một khối mã nơi có khả năng xảy ra ngoại lệ được đặt trong khối "try". Nếu ngoại lệ không xảy ra, mã sẽ tiếp tục thực thi. Tuy nhiên, nếu ngoại lệ xảy ra, nó sẽ được "ném" ra. Việc thực thi sẽ bị dừng lại và PHP sẽ tìm kiếm khối "catch" tương ứng. Nếu ngoại lệ không được bắt, PHP sẽ phát sinh một lỗi nghiêm trọng (Fatal Error).

  • Throw − Đây là cách bạn kích hoạt một ngoại lệ. Mỗi "throw" phải có ít nhất một khối "catch" hoặc "finally".

  • Catch − một khối mã lấy một ngoại lệ và tạo ra một đối tượng chứa thông tin về ngoại lệ đó. Nhiều khối catch có thể được sử dụng để bắt các ngoại lệ khác nhau.

  • Finally − Mã trong khối finally luôn được thực thi sau khối throw hoặc catch.

Example

Dưới đây là một ví dụ về kỹ thuật xử lý ngoại lệ. Đoạn mã này hiển thị hai trường văn bản trên trình duyệt và yêu cầu người dùng nhập hai số để thực hiện phép chia. Nếu số thứ hai (mẫu số) là 0, một ngoại lệ sẽ được ném ra và chương trình sẽ vào khối catch và in ra thông điệp ngoại lệ. Nếu không, kết quả của phép chia sẽ được hiển thị.

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

Nó sẽ tạo ra output

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

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

The Exception Class

PHP ném một đối tượng của Exception class . Trong PHP, lớp Exception là lớp cơ sở cho các ngoại lệ người dùng. Nó triển khai giao diện throwable.

Lớp này định nghĩa các phương thức sau đây −

getMessage()

Hàm này trả về thông điệp Exception dưới dạng chuỗi −

final public Exception::getMessage(): string

getCode()

Hàm này trả về mã ngoại lệ là int trong Exception −

final public Exception::getCode(): int

Hãy xem xét đoạn sau example

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

getFile()

Hàm này trả về tên tệp mà trong đó ngoại lệ đã được tạo ra −

final public Exception::getFile(): string

Hãy xem xét đoạn sau 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();
}

Nó sẽ tạo ra output

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

getLine()

Hàm này trả về số dòng nơi ngoại lệ được tạo ra −

final public Exception::getLine(): int

Example

Hãy xem xét ví dụ sau −

<?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();
      }
   }
?>

Nó sẽ tạo ra output

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

Multiple Catch Blocks

PHP cho phép một chuỗi các khối catch theo sau một khối try để xử lý các trường hợp ngoại lệ khác nhau. Nhiều khối catch có thể được sử dụng để xử lý các ngoại lệ và lỗi đã được định nghĩa trước cũng như các ngoại lệ do người dùng định nghĩa.

Example

Ví dụ sau sử dụng các khối catch để xử lý các điều kiện DivisioByZeroError, TypeError, ArgumentCountError và InvalidArgumentException. Cũng có một khối catch để xử lý ngoại lệ chung 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();
   }	
?>

Để bắt đầu, vì mẫu số là 0, lỗi "chia cho 0" sẽ được hiển thị −

Division by 0

Đặt $b=3 sẽ gây ra TypeError vì hàm divide dự kiến trả về số nguyên nhưng phép chia cho kết quả là float .

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

Nếu chỉ một biến được truyền vào hàm chia bằng cách thay đổi $res=divide($a); , điều này sẽ dẫn đến một ArgumentCountError .

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

Nếu một trong các đối số không phải là số nguyên, đó là trường hợp của InvalidArgumentException . Thay đổi $b thành một chuỗi −

Invalid type of arguments

The Finally Block

Một khối finally cũng có thể được chỉ định sau hoặc thay thế cho các khối catch . Mã trong khối finally sẽ luôn được thực thi sau các khối try catch , bất kể có xảy ra ngoại lệ hay không, và trước khi việc thực thi bình thường tiếp tục.

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>";
}

Nó sẽ tạo ra đầu ra sau đây −

Case 1 −

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

Case 2 −

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

Finally With Return

Có một hành vi đặc biệt của khối finally khi khối try hoặc khối catch (hoặc cả hai) chứa một câu lệnh return . Thông thường, một câu lệnh return sẽ khiến điều khiển chương trình quay trở lại vị trí gọi. Tuy nhiên, trong trường hợp của một hàm với khối try/catch có return , các câu lệnh trong khối finally sẽ được thực thi trước khi trở về.

Example

Trong ví dụ sau, hàm div() có cấu trúc "try-catch-finally". Khối try không có ngoại lệ sẽ trả về kết quả của phép chia. Trong trường hợp có ngoại lệ, khối catch sẽ trả về một thông báo lỗi. Tuy nhiên, trong cả hai trường hợp, câu lệnh trong khối finally sẽ được thực thi trước.

<?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);
?>

Nó sẽ tạo ra output

This block is always executed
Division by 0