Menu
Coddy logo textTech

Классы исключений

Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy. Урок 66 из 91.

В PHP исключения — это объекты, используемые для сигнала о том, что во время выполнения что-то пошло не так. Базовый класс для всех исключений — Exception, и понимание его структуры помогает эффективно обрабатывать ошибки в ваших OOP-приложениях.

Когда вы выбрасываете исключение, вы создаёте экземпляр класса Exception (или его подкласса) с сообщением, описывающим, что пошло не так:

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

Это приведёт к ошибке с необработанным исключением и сообщением "Insufficient funds".

PHP предоставляет несколько встроенных классов исключений для разных ситуаций. InvalidArgumentException сигнализирует о некорректных входных данных, RuntimeException указывает на ошибки во время выполнения, а LogicException представляет ошибки программирования:

<?php
class Calculator {
    public function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("Cannot divide by zero");
        }
        return $a / $b;
    }
}

Каждый объект исключения содержит полезную информацию: getMessage() возвращает сообщение об ошибке, getCode() возвращает необязательный код ошибки, а getFile() и getLine() сообщают, где было выброшено исключение. Использование конкретных типов исключений делает назначение вашего кода более понятным и позволяет выполнять более точную обработку ошибок.

challenge icon

Задание

Легко

Давайте создадим систему управления inventory, которая использует встроенные классы исключений PHP для сигнализации о разных типах проблем. Вы создадите inventory продуктов, в которой operation могут завершаться определёнными, понятными способами.

Вы распределите свой код по трём файлам:

  • Product.php: Создайте Product class, представляющий элемент в inventory. Используйте продвижение параметров конструктора для публичного $sku (string), публичного $name (string) и приватного $quantity (int). Ваш class должен содержать:
    • Метод getQuantity(): int, который возвращает current quantity
    • Метод addStock(int $amount): void, который увеличивает quantity. Если amount меньше 1, выбросьте InvalidArgumentException с сообщением "Amount must be positive"
    • Метод removeStock(int $amount): void, который уменьшает quantity. Если amount меньше 1, выбросьте InvalidArgumentException с сообщением "Amount must be positive". Если amount превышает current quantity, выбросьте RuntimeException с сообщением "Insufficient stock"
  • Inventory.php: Создайте Inventory class, который управляет коллекцией продуктов. Подключите файл Product. Ваш class должен содержать:
    • Приватный array для хранения продуктов, indexed по SKU
    • Метод addProduct(Product $product): void, который добавляет продукт. Если продукт с тем же SKU already exists, выбросьте LogicException с сообщением "Product already exists: [sku]"
    • Метод getProduct(string $sku): Product, который возвращает продукт по SKU. Если продукт не found, выбросьте InvalidArgumentException с сообщением "Product not found: [sku]"
  • main.php: Подключите файл Inventory. Вы получите три inputs: SKU, название продукта и operation ("add", "remove" или "duplicate").

    Создайте Inventory и добавьте новый Product с given SKU, названием и initial quantity, равным 10.

    Based on operation:

    • "add": Call addStock(5) для продукта, затем выведите "Stock updated: [quantity]"
    • "remove": Call removeStock(15) для продукта (это должно выбросить exception)
    • "duplicate": Попробуйте добавить another продукт с тем же SKU (это должно выбросить exception)

    Когда выбрасывается exception, выведите имя его class, followed by ": ", и message исключения. Используйте PHP get_class() function, чтобы получить имя class.

Этот challenge демонстрирует, как разные типы исключений сообщают о разных видах проблем: недопустимых inputs, сбоях во время выполнения и ошибках логики, благодаря чему обработка ошибок в вашем коде становится более точной и понятной.

Попробуйте сами

<?php

require_once 'Inventory.php';

// Считать входные данные
$sku = trim(fgets(STDIN));
$name = trim(fgets(STDIN));
$operation = trim(fgets(STDIN));

try {
    // TODO: Создать Inventory
    // TODO: Создать Product с заданными SKU, name и начальным количеством 10
    // TODO: Добавить product в inventory
    
    // TODO: В зависимости от operation:
    // - "add": Call addStock(5) on the product, then print "Stock updated: [quantity]"
    // - "remove": Вызвать removeStock(15) у product
    // - "duplicate": Попытаться добавить другой product с тем же SKU
    
} catch (Exception $e) {
    // TODO: Вывести имя класса исключения, за которым следует ": " и сообщение
    // Hint: Используйте get_class($e), чтобы получить имя класса
}

?>
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор PHP