Menu
Coddy logo textTech

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.

challenge icon

Wyzwanie

Łatwy

Zbudujmy 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 InvalidQuantityException i wyświetl "Quantity error: [message] (value: [quantity])", korzystając z komunikatu wyjątku i metody getQuantity(). Następnie przechwyć wyjątek OutOfStockException i wyświetl "Stock error: [message] (product: [productName])", korzystając z komunikatu wyjątku i metody getProductName().

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

?>
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Programowanie obiektowe

Poćwicz samodzielnie: Kompilator PHP online