Xử lý ngoại lệ PHP
- Trang trước PHP Lỗi
- Trang tiếp theo PHP Filter
Ngoại lệ (Exception) được sử dụng để thay đổi luồng bình thường của脚本 khi xảy ra lỗi cụ thể.
Gì là ngoại lệ?
PHP 5 cung cấp một phương pháp xử lý lỗi hướng đối tượng mới.
Xử lý ngoại lệ được sử dụng để thay đổi luồng bình thường của脚本 khi xảy ra lỗi (ngoại lệ) cụ thể. Tình huống này được gọi là ngoại lệ.
Khi ngoại lệ được kích hoạt, thường xảy ra:
- Trạng thái mã hiện tại được lưu trữ
- Việc thực thi mã được chuyển đổi sang hàm bộ xử lý ngoại lệ tiền định
- Tùy thuộc vào tình huống, bộ xử lý có thể bắt đầu lại mã từ trạng thái lưu trữ, kết thúc việc thực thi脚本, hoặc tiếp tục thực thi mã từ vị trí khác trong mã
Chúng ta sẽ trình bày các phương pháp xử lý lỗi khác nhau:
- Cách sử dụng cơ bản của ngoại lệ
- Tạo bộ xử lý ngoại lệ tùy chỉnh
- Nhiều lỗi
- Ném lại lỗi
- Đặt bộ xử lý ngoại lệ cấp cao
Cách sử dụng cơ bản của ngoại lệ
Khi ngoại lệ được ném ra, mã sau nó sẽ không tiếp tục thực thi, PHP sẽ cố gắng tìm khối mã "catch" phù hợp.
Nếu ngoại lệ không được bắt và không sử dụng set_exception_handler() để xử lý phù hợp, thì sẽ xảy ra lỗi nghiêm trọng (lỗi nghiêm trọng), và hiển thị thông điệp lỗi "Uncaught Exception" (Ngoại lệ không được bắt).
Hãy thử ném ra một ngoại lệ mà không bắt nó:
<?php //tạo hàm với ngoại lệ function checkNum($number) { if($number>1) { throw new Exception("Giá trị phải là 1 hoặc dưới"); } return true; } //kích hoạt ngoại lệ checkNum(2); ?>
Mã trên sẽ nhận được lỗi tương tự như sau:
Lỗi nghiêm trọng: ngoại lệ không được bắt với thông điệp 'Giá trị phải là 1 hoặc nhỏ hơn' trong C:\webfolder\test.php:6 Gọi lại stack trace: #0 C:\webfolder\test.php(12): checkNum(28) #1 {main} ném ra trong C:\webfolder\test.php trên dòng 6
Try, throw và catch
Để tránh lỗi như trong ví dụ trên, chúng ta cần tạo mã phù hợp để xử lý ngoại lệ.
Chương trình xử lý chính xác nên bao gồm:
- Thử - Các hàm gây ra ngoại lệ nên được đặt trong khối mã "try". Nếu không có ngoại lệ xảy ra, mã sẽ tiếp tục thực thi bình thường. Nhưng nếu ngoại lệ được kích hoạt, nó sẽ ném ra một ngoại lệ.
- Ném ra - Ở đây quy định cách gây ra exception. Mỗi "throw" phải có ít nhất một "catch"
- Bắt - Khối mã "catch" sẽ bắt exception, và tạo một đối tượng chứa thông tin exception
Hãy ném ra một exception:
<?php //Tạo hàm có thể ném ra exception function checkNum($number) { if($number>1) { throw new Exception("Giá trị phải là 1 hoặc dưới"); } return true; } //Gây ra exception trong khối mã "try" try { checkNum(2); //Nếu exception được ném ra, văn bản này sẽ không được hiển thị echo 'Nếu bạn thấy điều này, số là 1 hoặc dưới'; } //Bắt exception catch(Exception $e) { echo 'Tin nhắn: ' .$e->getMessage(); } ?>
Mã trên sẽ nhận được lỗi tương tự như sau:
Tin nhắn: Giá trị phải là 1 hoặc dưới
Giải thích ví dụ:
Mã trên đã ném ra một exception và bắt nó:
- Tạo hàm checkNum(). Nó kiểm tra số liệu có lớn hơn 1 hay không. Nếu có, nó sẽ ném ra một exception.
- Gọi hàm checkNum() trong khối mã "try".
- Lỗi trong hàm checkNum() bị ném ra
- Mã lệnh "catch" nhận được exception này và tạo một đối tượng chứa thông tin exception ($e).
- Bằng cách gọi hàm $e->getMessage() từ đối tượng exception, xuất ra thông báo lỗi từ exception đó
Nhưng, để tuân thủ nguyên tắc “mỗi throw phải có một catch”, có thể thiết lập một bộ xử lý exception cấp cao để xử lý các lỗi bị bỏ sót.
Tạo một lớp Exception tùy chỉnh
Tạo một bộ xử lý exception tùy chỉnh rất đơn giản. Chúng ta chỉ cần tạo một lớp chuyên biệt, khi có lỗi xảy ra trong PHP, có thể gọi các hàm của nó. Lớp này phải là một mở rộng của lớp exception.
Lớp exception tùy chỉnh này kế thừa tất cả các thuộc tính của lớp exception của PHP, bạn có thể thêm các hàm tùy chỉnh.
Chúng ta bắt đầu tạo lớp exception:
<?php class customException extends Exception { public function errorMessage() { //thông báo lỗi $errorMsg = 'Lỗi trên dòng '.$this->getLine().' trong '.$this->getFile() : <b>'.$this->getMessage().'</b> không phải là địa chỉ email hợp lệ return $errorMsg; } } $email = "người@example...com"; try { //kiểm tra nếu if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //ném lỗi nếu email không hợp lệ throw new customException($email); } } catch (customException $e) { //hiển thị thông báo tùy chỉnh echo $e->errorMessage(); } ?>
Lớp mới này là bản sao của lớp exception cũ, thêm vào hàm errorMessage(). Do đó, nó kế thừa thuộc tính và phương thức từ lớp cũ, chúng ta có thể sử dụng các phương thức của lớp exception, chẳng hạn như getLine(), getFile() và getMessage().
Giải thích ví dụ:
Mã trên đã ném ra một lỗi và bắt nó bằng một lớp exception tùy chỉnh:
- Lớp customException() được tạo ra như một mở rộng của lớp exception cũ. Như vậy nó kế thừa tất cả các thuộc tính và phương thức của lớp cũ.
- Tạo hàm errorMessage(). Nếu địa chỉ email không hợp lệ, hàm này sẽ trả về một thông báo lỗi
- Đặt biến $email thành chuỗi địa chỉ email không hợp lệ
- Thực hiện khối mã "try", do địa chỉ email không hợp lệ, vì vậy ném ra một lỗi
- Khối mã "catch" bắt lỗi và hiển thị thông báo lỗi
Nhiều lỗi
Bạn có thể sử dụng nhiều lỗi cho một đoạn mã để kiểm tra nhiều trường hợp.
Bạn có thể sử dụng nhiều khối mã if..else hoặc một khối mã switch, hoặc nhúng nhiều lỗi. Các lỗi này có thể sử dụng các lớp exception khác nhau và trả về các thông báo lỗi khác nhau:
<?php class customException extends Exception { public function errorMessage() { //thông báo lỗi $errorMsg = 'Lỗi trên dòng '.$this->getLine().' trong '.$this->getFile() : <b>'.$this->getMessage().'</b> không phải là địa chỉ email hợp lệ return $errorMsg; } } $email = "someone@example.com"; try { //kiểm tra nếu if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //ném lỗi nếu email không hợp lệ throw new customException($email); } //kiểm tra xem "example" có trong địa chỉ email hay không if(strpos($email, "example") !== FALSE) { throw new Exception("$email is an example e-mail"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>
Giải thích ví dụ:
Mã trên đã kiểm tra hai điều kiện, nếu bất kỳ điều kiện nào không thành lập, thì ném ra một lỗi:
- Lớp customException() được tạo ra như một mở rộng của lớp exception cũ. Như vậy nó kế thừa tất cả các thuộc tính và phương thức của lớp cũ.
- Tạo hàm errorMessage(). Nếu địa chỉ email không hợp lệ, hàm này sẽ trả về một thông báo lỗi.
- Thực hiện khối mã "try", trong điều kiện đầu tiên, không ném lỗi.
- Do email chứa chuỗi "example", điều kiện thứ hai sẽ kích hoạt lỗi.
- Khối mã "catch" sẽ bắt lỗi và hiển thị thông báo lỗi hợp lý
Nếu không bắt được customException, chỉ bắt được base exception, thì xử lý lỗi ở đó.
Ném lại lỗi
Thỉnh thoảng, khi gặp lỗi, bạn có thể muốn xử lý nó theo cách khác biệt so với tiêu chuẩn. Bạn có thể ném lại lỗi trong một khối mã "catch".
Văn bản nên ẩn lỗi hệ thống khỏi người dùng. Đối với người lập trình, lỗi hệ thống có thể rất quan trọng, nhưng người dùng không quan tâm đến chúng. Để người dùng dễ sử dụng hơn, bạn có thể ném lại lỗi với thông báo hữu ích hơn cho người dùng:
<?php class customException extends Exception { public function errorMessage() { //thông báo lỗi $errorMsg = $this->getMessage().' is not a valid E-Mail address.'; return $errorMsg; } } $email = "someone@example.com"; try { try { //kiểm tra xem "example" có trong địa chỉ email hay không if(strpos($email, "example") !== FALSE) { //ném lỗi nếu email không hợp lệ throw new Exception($email); } } catch(Exception $e) { //ném lỗi lại throw new customException($email); } } catch (customException $e) { //hiển thị thông báo tùy chỉnh echo $e->errorMessage(); } ?>
Giải thích ví dụ:
Mã trên này kiểm tra xem chuỗi "example" có trong địa chỉ email hay không. Nếu có, thì ném lỗi lại:
- Lớp customException() được tạo ra như một mở rộng của lớp exception cũ. Như vậy nó kế thừa tất cả các thuộc tính và phương thức của lớp cũ.
- Tạo hàm errorMessage(). Nếu địa chỉ email không hợp lệ, hàm này sẽ trả về một thông báo lỗi.
- Đặt biến $email thành một địa chỉ email hợp lệ nhưng chứa chuỗi "example".
- Mã trong khối "try" chứa một khối "try" khác, từ đó có thể ném lỗi lại.
- Vì email chứa chuỗi "example", nên lỗi được kích hoạt.
- "catch" bắt được lỗi này và ném lại "customException".
- Gặp lỗi "customException" và hiển thị một thông báo lỗi.
Nếu ngoại lệ không được bắt trong khối mã try hiện tại, nó sẽ tìm kiếm khối mã catch ở cấp cao hơn.
Thiết lập bộ xử lý ngoại lệ cấp cao nhất (Top Level Exception Handler)
Hàm set_exception_handler() có thể thiết lập hàm người dùng định nghĩa để xử lý tất cả ngoại lệ không được bắt.
<?php function myException($exception) { echo "<b>Ngoại lệ:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Ngoại lệ không được bắt'); ?>
Output của mã trên nên tương tự như sau:
Exception: Ngoại lệ không được bắt
Trong mã trên, không có khối mã catch, mà là chương trình xử lý ngoại lệ cấp cao nhất được kích hoạt. Bạn nên sử dụng hàm này để bắt tất cả ngoại lệ không được bắt.
Quy tắc ngoại lệ
- Mã cần xử lý ngoại lệ nên được đặt trong khối mã try để bắt ngoại lệ tiềm ẩn.
- Mỗi khối mã try hoặc throw phải có ít nhất một khối mã catch tương ứng.
- Việc sử dụng nhiều khối mã catch có thể bắt được nhiều loại ngoại lệ khác nhau.
- Bạn có thể ném (re-thrown) ngoại lệ lại trong khối mã catch trong khối mã try.
Nói một cách ngắn gọn: Nếu có ngoại lệ xảy ra, bạn phải bắt nó.
- Trang trước PHP Lỗi
- Trang tiếp theo PHP Filter