Menu
Coddy logo textTech

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.

challenge icon

Wyzwanie

Łatwy

Zbudujmy 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ątek InvalidArgumentException z komunikatem "Amount must be positive"
    • Metodę removeStock(int $amount): void, która zmniejsza ilość. Jeśli wartość amount jest mniejsza niż 1, rzuć wyjątek InvalidArgumentException z komunikatem "Amount must be positive". Jeśli wartość amount przekracza bieżącą ilość, rzuć wyjątek RuntimeException z komunikatem "Insufficient stock"
  • 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ątek LogicException z 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ątek InvalidArgumentException z 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 Inventory i dodaj nowy produkt Product z podanym SKU, nazwą i początkową ilością 10.

    W zależności od operacji:

    • "add": Wywołaj na produkcie addStock(5), a następnie wypisz "Stock updated: [quantity]"
    • "remove": Wywołaj na produkcie removeStock(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 PHP get_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
}

?>
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