Zarządzanie wyjątkami w PHP
Wyjątek (Exception) służy do zmiany normalnego przepływu skryptu w określonych sytuacjach błędów.
Co to jest wyjątek?
PHP 5 oferuje nową metodę obiektowego przetwarzania błędów.
Przetwarzanie wyjątków służy do zmiany normalnego przepływu skryptu w określonych sytuacjach błędów (wyjątków). Ta sytuacja nazywa się wyjątkiem.
Kiedy wyjątek jest wywoływany, zazwyczaj dzieje się następujące:
- Bieżący stan kodu zostanie zachowany
- Wykonywanie kodu przełączy się na zdefiniowaną funkcję handlera wyjątków
- W zależności od sytuacji, handler może zacząć wykonywać kod od zachowanego stanu kodu, zakończyć wykonywanie skryptu lub kontynuować wykonywanie skryptu z innej lokalizacji kodu
Pokażemy różne metody przetwarzania błędów:
- Podstawowe użycie wyjątków
- Tworzenie własnego handlera wyjątków
- Wiele wyjątków
- Ponowne rzuwanie wyjątku
- Ustawienie górnego handlera wyjątków
Podstawowe użycie wyjątków
Kiedy wyjątek jest rzucony, kod po nim nie będzie kontynuował wykonywania się, PHP spróbuje znaleźć dopasowany blok kodu "catch".
Jeśli wyjątek nie zostanie złapany i nie zostanie użyty set_exception_handler() do odpowiedniego przetwarzania, dojdzie do poważnego błędu (krytycznego błędu), i zostanie wyświetlony komunikat błędu "Nie złapany wyjątek" (nie złapany wyjątek).
Spróbujmy rzucić wyjątek, nie łapiąc go:
<?php //stwórz funkcję z wyjątkiem function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //wywołaj wyjątek checkNum(2); ?>
Powyższy kod może wywołać błąd podobny do tego:
Błąd krytyczny: Niespodziewany wyjątek 'Exception' z komunikatem 'Wartość musi być 1 lub poniżej' w C:\webfolder\test.php:6 Śledzenie stosu: #0 C:\webfolder\test.php(12): checkNum(28) #1 {main} rzucony w C:\webfolder\test.php w wierszu 6
Try, throw i catch
Aby uniknąć błędów z powyższego przykładu, musimy stworzyć odpowiedni kod do przetwarzania wyjątków.
Poprawne przetwarzanie powinno obejmować:
- Spróbuj - funkcje wyjątkowe powinny być umieszczone w bloku kodu "try". Jeśli wyjątek nie zostanie wywołany, kod będzie kontynuował normalne wykonywanie. Ale jeśli wyjątek zostanie wywołany, zostanie rzucony wyjątek.
- Throw - Tutaj określa się, jak wywołać wyjątek. Każdy "throw" musi mieć przynajmniej jeden "catch"
- Catch - Blok "catch" przechwytuje wyjątek i tworzy obiekt zawierający informacje o wyjątku
Pozwólmy wywołać wyjątek:
<?php //Tworzenie funkcji, która może rzucać wyjątek function checkNum($number) { if($number>1) { throw new Exception("Value must be 1 or below"); } return true; } //Wywołanie wyjątku w bloku kodu "try" try { checkNum(2); //Jeśli wyjątek zostanie rzucony, ten tekst nie zostanie wyświetlony echo 'If you see this, the number is 1 or below'; } //Złapanie wyjątku catch(Exception $e) { echo 'Message: ' .$e->getMessage(); } ?>
Powyższy kod może wyświetlić podobny błąd:
Message: Value must be 1 or below
例子解释:
Powyższy kod rzuca wyjątek i go łapie:
- Tworzenie funkcji checkNum(). Sprawdza, czy liczba jest większa niż 1. Jeśli tak, rzuca wyjątek.
- Wywołanie funkcji checkNum() w bloku kodu "try".
- Wyjątek w funkcji checkNum() jest rzucony
- Bloki kodu "catch" odbierają ten wyjątek i tworzą obiekt zawierający informacje o wyjątku ($e).
- Przez wywołanie $e->getMessage() z tego obiektu exception, wyświetlana jest komunikat błędu z tego wyjątku
Aby przestrzegać zasady „każdy throw musi mieć odpowiedni catch”, można ustawić wierzchołkowy program obsługi wyjątków, aby obsługiwał pominięte błędy.
Tworzenie niestandardowej klasy Exception
Tworzenie niestandardowego programu obsługi wyjątków jest bardzo proste. Prosto tworzymy specjalną klasę, do której można wywołać funkcje, gdy w PHP wystąpi wyjątek. Klasa musi być rozszerzeniem klasy exception.
Ta niestandardowa klasa exception dziedziczy wszystkie atrybuty klasy exception PHP, możesz dodać do niej niestandardowe funkcje.
Zaczynamy tworzyć klasę exception:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() : <b>'.$this->getMessage().'</b> nie jest poprawnym adresem e-mail return $errorMsg; } } $email = "someone@example...com"; try { //Sprawdź, czy if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
Nowa klasa jest kopią starej klasy wyjątków, dodając funkcję errorMessage(). Ponieważ jest kopią starej klasy, dziedziczy atrybuty i metody ze starej klasy, możemy używać metod klasy wyjątków, takich jak getLine(), getFile() oraz getMessage().
例子解释:
Powyższy kod rzuca wyjątek i uchwytuje go za pomocą własnej klasy wyjątków:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- Utwórz funkcję errorMessage(). Jeśli adres e-mail jest nielegalny, funkcja ta zwraca wiadomość o błędzie
- Ustaw zmienną $email na ciąg znaków adresu e-mail nielegalnego
- Wykonaj blok "try", ponieważ adres e-mail jest nielegalny, zostanie rzucony wyjątek
- Blok "catch" uchwytuje wyjątek i wyświetla wiadomość o błędzie
Wiele wyjątków
Możesz użyć wielu wyjątków dla jednego skryptu, aby wykryć różne sytuacje.
Możesz użyć wielu bloków if..else, lub jednego bloku switch, lub wielokrotnego wcięcia wyjątków. Te wyjątki mogą używać różnych klas wyjątków i zwracać różne wiadomości o błędach:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = 'Error on line '.$this->getLine().' in '.$this->getFile() : <b>'.$this->getMessage().'</b> nie jest poprawnym adresem e-mail return $errorMsg; } } $email = "someone@example.com"; try { //Sprawdź, czy if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //throw exception if email is not valid throw new customException($email); } //check for "example" in mail address 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(); } ?>
例子解释:
Powyższy kod testuje dwa warunki, jeśli żaden z nich nie jest spełniony, zostanie rzucony wyjątek:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
- Wykonaj blok "try", pod warunkiem pierwszym, wyjątek nie zostanie rzucony.
- Ponieważ e-mail zawiera ciąg "example", druga warunek wywoła wyjątek.
- Blok "catch" uchwytuje wyjątek i wyświetla odpowiednią wiadomość o błędzie
Jeśli nie uchwyciliśmy customException, ale tylko base exception, przetwarzaj wyjątek tam.
Ponowne rzuwanie wyjątku
Czasami, gdy wyjątek jest rzucony, możesz chcieć go przetworzyć w sposób inny niż standardowy. Możesz ponownie rzucać wyjątek w bloku "catch".
The script should hide system errors from the user. System errors may be important for programmers, but users are not interested in them. To make it easier for users, you can re-throw exceptions with user-friendly messages:
<?php class customException extends Exception { public function errorMessage() { //error message $errorMsg = $this->getMessage().' is not a valid E-Mail address.'; return $errorMsg; } } $email = "someone@example.com"; try { try { //check for "example" in mail address if(strpos($email, "example") !== FALSE) { //throw exception if email is not valid throw new Exception($email); } } catch(Exception $e) { //re-throw exception throw new customException($email); } } catch (customException $e) { //display custom message echo $e->errorMessage(); } ?>
例子解释:
上面的代码检测在邮件地址中是否含有字符串 "example"。如果有,则再次抛出异常:
- customException() 类是作为旧的 exception 类的一个扩展来创建的。这样它就继承了旧类的所有属性和方法。
- 创建 errorMessage() 函数。如果 e-mail 地址不合法,则该函数返回一个错误消息。
- 把 $email 变量设置为一个有效的邮件地址,但含有字符串 "example"。
- "try" 代码块包含另一个 "try" 代码块,这样就可以再次抛出异常。
- 由于 e-mail 包含字符串 "example",因此触发异常。
- "catch" 捕获到该异常,并重新抛出 "customException"。
- 捕获到 "customException",并显示一条错误消息。
Jeśli wyjątek nie został ujęty w bieżącym bloku try, zostanie poszukiwany w wyższym poziomie bloków catch.
Ustawienie najwyższego poziomu handlera wyjątków (Top Level Exception Handler)
Funkcja set_exception_handler() może ustawić użytkownika-defined funkcję do obsługi wszystkich nieuchwyconych wyjątków.
<?php function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Uncaught Exception occurred'); ?>
Wyjście powyższego kodu powinno wyglądać podobnie:
Exception: Uncaught Exception occurred
W powyższym kodzie nie istnieje blok catch, ale jest uruchamiany program异常处理程序。Należy użyć tej funkcji, aby ująć wszystkie nieuchwycone wyjątki.
Zasady wyjątków
- Kod wymagający obsługi wyjątków powinien być umieszczony w bloku try, aby ująć potencjalne wyjątki.
- Każdy blok try lub throw musi mieć przynajmniej jeden blok catch.
- Użycie wielu bloków catch pozwala na ujęcie różnych rodzajów wyjątków.
- Można ponownie rzucać (re-thrown) wyjątki w bloku catch kodu try.
Krótko mówiąc: jeśli wyjątek został rzucony, musi zostać ujęty.