Niestandardowa hierarchia wyjątków
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 67 z 91.
Chociaż wbudowane klasy wyjątków PHP obejmują typowe scenariusze, rzeczywiste aplikacje często potrzebują bardziej specyficznych typów błędów. Utworzenie własnej hierarchii wyjątków pozwala definiować wyjątki dopasowane do Twojej domeny i przechwytywać je na różnych poziomach szczegółowości.
Aby utworzyć własny wyjątek, po prostu rozszerz klasę Exception lub jedną z jej podklas:
<?php
class PaymentException extends Exception {}
class InsufficientFundsException extends PaymentException {
public function __construct(
private float $required,
private float $available
) {
parent::__construct("Need $required but only $available available");
}
public function getShortfall(): float {
return $this->required - $this->available;
}
}
Zauważ, że InsufficientFundsException dziedziczy po PaymentException, a nie bezpośrednio po Exception. Tworzy to hierarchię, dzięki której możesz przechwycić wszystkie wyjątki związane z płatnościami w jednym bloku catch albo obsłużyć je osobno.
Własne wyjątki mogą zawierać dodatkowe właściwości i metody związane z błędem. Tutaj getShortfall() dostarcza przydatnych informacji, których nie mógłby zaoferować ogólny wyjątek:
<?php
class Wallet {
public function __construct(private float $balance) {}
public function pay(float $amount): void {
if ($amount > $this->balance) {
throw new InsufficientFundsException($amount, $this->balance);
}
$this->balance -= $amount;
}
}
Dobrze zaprojektowana hierarchia wyjątków ułatwia utrzymanie kodu. Podczas przechwytywania wyjątków możesz działać ogólnie lub szczegółowo, zależnie od potrzeb, a same obiekty wyjątków zawierają istotne informacje o tym, co poszło nie tak.
Wyzwanie
ŁatwyZbudujmy system przetwarzania zamówień z hierarchią niestandardowych wyjątków, która obsługuje różne rodzaje błędów związanych z zamówieniami. Utworzysz wyjątki zawierające istotne informacje o tym, co poszło nie tak, dzięki czemu obsługa błędów będzie dokładniejsza i bardziej czytelna.
Rozmieścisz swój kod w czterech plikach:
OrderException.php: Utwórz bazową klasęOrderException, która rozszerza klasęException. Będzie ona klasą nadrzędną dla wszystkich wyjątków związanych z zamówieniami, dzięki czemu w razie potrzeby można będzie przechwycić dowolny problem z zamówieniem za pomocą jednego bloku catch.OutOfStockException.php: Utwórz klasęOutOfStockException, która rozszerza klasęOrderException. Ten wyjątek powinien przyjmować w konstruktorze nazwę produktu i żądaną ilość. Użyj promocji właściwości konstruktora dla tych prywatnych właściwości. Wywołaj konstruktor klasy nadrzędnej, przekazując komunikat w formacie"[productName] is out of stock (requested: [quantity])". Dodaj metodęgetProductName(): string, która zwraca nazwę produktu.InvalidQuantityException.php: Utwórz klasęInvalidQuantityException, która rozszerza klasęOrderException. Ten wyjątek powinien przyjmować w konstruktorze wartość ilości, używając promocji właściwości konstruktora dla prywatnej właściwości. Wywołaj konstruktor klasy nadrzędnej, przekazując komunikat"Invalid quantity: [quantity]". Dodaj metodęgetQuantity(): int, która zwraca wartość ilości.main.php: Dołącz wszystkie trzy pliki z wyjątkami. Otrzymasz dwa dane wejściowe: nazwę produktu i ilość (jako ciąg znaków, który należy przekonwertować na liczbę całkowitą).Na podstawie wartości ilości rzuć odpowiedni wyjątek:
- Jeśli ilość jest mniejsza niż 1, rzuć wyjątek
InvalidQuantityException - Jeśli ilość jest większa niż 100, rzuć wyjątek
OutOfStockException(symulując brak wystarczających zapasów) - W przeciwnym razie wyświetl
"Order placed: [quantity]x [productName]"
Przechwytuj wyjątki zgodnie z hierarchią. Najpierw przechwyć wyjątek
InvalidQuantityExceptioni wyświetl"Quantity error: [message] (value: [quantity])", korzystając z komunikatu wyjątku i metodygetQuantity(). Następnie przechwyć wyjątekOutOfStockExceptioni wyświetl"Stock error: [message] (product: [productName])", korzystając z komunikatu wyjątku i metodygetProductName().- Jeśli ilość jest mniejsza niż 1, rzuć wyjątek
Ta hierarchia pozwala obsługiwać konkretne wyjątki indywidualnie, a jednocześnie zachowuje możliwość przechwycenia wszystkich problemów związanych z zamówieniami za pomocą bazowej klasy OrderException. Niestandardowe metody w każdej klasie wyjątku dostarczają kontekstu, którego nie zapewniłby ogólny wyjątek.
Spróbuj swoich sił
<?php
// Dołącz wszystkie pliki wyjątków
require_once 'OrderException.php';
require_once 'OutOfStockException.php';
require_once 'InvalidQuantityException.php';
// Odczytaj dane wejściowe
$productName = trim(fgets(STDIN));
$quantity = intval(trim(fgets(STDIN)));
// TODO: Użyj try-catch do obsługi przetwarzania zamówienia
// Wewnątrz bloku try:
// - Jeśli quantity < 1, zgłoś InvalidQuantityException
// - Jeśli quantity > 100, zgłoś OutOfStockException
// - W przeciwnym razie wypisz "Order placed: [quantity]x [productName]"
//
// Najpierw przechwyć InvalidQuantityException:
// - Wypisz "Quantity error: [message] (value: [quantity])", używając getMessage() i getQuantity()
//
// Przechwyć OutOfStockException:
// - Wypisz "Stock error: [message] (product: [productName])", używając getMessage() i getProductName()
?>Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy programowania obiektowego
Pliki zewnętrzneWprowadzenie do programowania obiektowegoKlasy a obiektySłowo kluczowe $thisMetodyWłaściwościKonstruktor (__construct)Destruktor (__destruct)Powtórka — prosty kalkulator4Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe parent::Przesłanianie metodSłowo kluczowe finalKlasy abstrakcyjnePowtórzenie – hierarchia pracowników7Enkapsulacja
Public, protected, privateModyfikatory dostępu w szczegółachGettery i setteryUkrywanie informacjiPromocja parametrów konstruktora (8.0)Podsumowanie — system ewidencji studentów2Przestrzenie nazw i autoloading
Wprowadzenie do przestrzeni nazwSłowo kluczowe useStandard autoloadingu PSR-4Autoloader ComposeraPodsumowanie – uporządkowany projekt5Interfejsy i kontrakty
Wprowadzenie do interfejsówImplementowanie interfejsówImplementowanie wielu interfejsówInterfejs a klasa abstrakcyjnaPodpowiadanie typów za pomocą interfejsówPodsumowanie — kalkulator kształtów8Metody magiczne
Wprowadzenie do metod magicznych__toString i __debugInfo__get, __set, __isset, __unset__call i __callStatic__clone i klonowanie obiektów__serialize i __unserializePodsumowanie — własna kolekcja11System typów i obsługa błędów
Deklaracje typówTypy nullableTypy sumy i przecięciaKlasy wyjątkówNiestandardowa hierarchia wyjątkówTry, Catch, FinallyPodsumowanie — walidator formularzy14Projekt: Zarządzanie biblioteką
Przegląd projektuKlasy książki i użytkownika3Właściwości klas
Właściwości instancji a właściwości statyczneStałe w klasachMetody i właściwości statyczneWłaściwości prywatne i chronioneWłaściwości tylko do odczytu (PHP 8.1)Podsumowanie — menedżer kont bankowych6Polimorfizm
Ponowne omówienie nadpisywania metodPolimorfizm za pomocą interfejsówPodpowiedzi typów i typy sumyPóźne wiązanie statycznePodsumowanie — procesor płatności9Cechy
Wprowadzenie do cechKorzystanie z wielu cechRozwiązywanie konfliktów cechMetody abstrakcyjne w cechachCechy a dziedziczenie12Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec StrategyPoćwicz samodzielnie: Kompilator PHP online