Klasy wyjątków
Część sekcji Programowanie obiektowe ścieżki PHP w Coddy. Lekcja 66 z 91.
W PHP wyjątki to obiekty służące do sygnalizowania, że podczas wykonywania programu coś poszło nie tak. Klasą bazową dla wszystkich wyjątków jest Exception, a zrozumienie jej struktury pomaga skutecznie obsługiwać błędy w aplikacjach OOP.
Gdy zgłaszasz wyjątek, tworzysz instancję klasy Exception (lub klasy pochodnej) z komunikatem opisującym, co poszło nie tak:
<?php
class BankAccount {
public function __construct(private float $balance = 0) {}
public function withdraw(float $amount): float {
if ($amount > $this->balance) {
throw new Exception("Insufficient funds");
}
$this->balance -= $amount;
return $amount;
}
}
$account = new BankAccount(100);
$account->withdraw(150);
Spowoduje to błąd nieprzechwyconego wyjątku z komunikatem „Insufficient funds”.
PHP udostępnia kilka wbudowanych klas wyjątków dla różnych sytuacji. InvalidArgumentException sygnalizuje nieprawidłowe dane wejściowe, RuntimeException wskazuje błędy podczas wykonywania, a LogicException reprezentuje błędy programistyczne:
<?php
class Calculator {
public function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
}
Każdy obiekt wyjątku zawiera przydatne informacje: getMessage() zwraca komunikat o błędzie, getCode() zwraca opcjonalny kod błędu, a getFile() i getLine() wskazują, gdzie został zgłoszony wyjątek. Używanie konkretnych typów wyjątków sprawia, że intencje Twojego kodu są jaśniejsze i umożliwia dokładniejszą obsługę błędów.
Wyzwanie
ŁatwyZbudujmy system zarządzania stanami magazynowymi, który wykorzystuje wbudowane klasy wyjątków PHP do sygnalizowania różnych rodzajów problemów. Utworzysz magazyn produktów, w którym operacje mogą kończyć się niepowodzeniem na konkretne, znaczące sposoby.
Rozmieścisz swój kod w trzech plikach:
Product.php: Utwórz klasęProduct, która reprezentuje produkt w magazynie. Użyj promocji właściwości konstruktora dla publicznego$sku(string), publicznego$name(string) i prywatnego$quantity(int). Twoja klasa powinna mieć:- Metodę
getQuantity(): int, która zwraca bieżącą ilość - Metodę
addStock(int $amount): void, która zwiększa ilość. Jeśli wartość amount jest mniejsza niż 1, rzuć wyjątekInvalidArgumentExceptionz komunikatem"Amount must be positive" - Metodę
removeStock(int $amount): void, która zmniejsza ilość. Jeśli wartość amount jest mniejsza niż 1, rzuć wyjątekInvalidArgumentExceptionz komunikatem"Amount must be positive". Jeśli wartość amount przekracza bieżącą ilość, rzuć wyjątekRuntimeExceptionz komunikatem"Insufficient stock"
- Metodę
Inventory.php: Utwórz klasęInventory, która zarządza kolekcją produktów. Dołącz plik Product. Twoja klasa powinna mieć:- Prywatną tablicę do przechowywania produktów indeksowanych według SKU
- Metodę
addProduct(Product $product): void, która dodaje produkt. Jeśli produkt o tym samym SKU już istnieje, rzuć wyjątekLogicExceptionz komunikatem"Product already exists: [sku]" - Metodę
getProduct(string $sku): Product, która zwraca produkt na podstawie SKU. Jeśli produkt nie zostanie znaleziony, rzuć wyjątekInvalidArgumentExceptionz komunikatem"Product not found: [sku]"
main.php: Dołącz plik Inventory. Otrzymasz trzy dane wejściowe: SKU, nazwę produktu i operację ("add","remove"lub"duplicate").Utwórz obiekt
Inventoryi dodaj nowy produktProductz podanym SKU, nazwą i początkową ilością10.W zależności od operacji:
"add": Wywołaj na produkcieaddStock(5), a następnie wypisz"Stock updated: [quantity]""remove": Wywołaj na produkcieremoveStock(15)(powinno to rzucić wyjątek)"duplicate": Spróbuj dodać kolejny produkt o tym samym SKU (powinno to rzucić wyjątek)
Gdy zostanie rzucony wyjątek, wypisz nazwę jego klasy, a następnie
": "i komunikat wyjątku. Użyj funkcji PHPget_class(), aby uzyskać nazwę klasy.
To wyzwanie pokazuje, jak różne typy wyjątków sygnalizują różne rodzaje problemów — nieprawidłowe dane wejściowe, błędy wykonania i błędy logiki — dzięki czemu obsługa błędów w Twoim kodzie jest bardziej precyzyjna i czytelna.
Spróbuj swoich sił
<?php
require_once 'Inventory.php';
// Odczytaj dane wejściowe
$sku = trim(fgets(STDIN));
$name = trim(fgets(STDIN));
$operation = trim(fgets(STDIN));
try {
// TODO: Utwórz Inventory
// TODO: Utwórz Product z podanym SKU, nazwą i początkową ilością 10
// TODO: Dodaj produkt do magazynu
// TODO: W zależności od operacji:
// - "add": Wywołaj addStock(5) dla produktu, a następnie wypisz "Stock updated: [quantity]"
// - "remove": Wywołaj removeStock(15) dla produktu
// - "duplicate": Spróbuj dodać kolejny produkt z tym samym SKU
} catch (Exception $e) {
// TODO: Wypisz nazwę klasy wyjątku, po niej ": " i komunikat
// Wskazówka: Użyj get_class($e), aby uzyskać nazwę klasy
}
?>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