Menu
Coddy logo textTech

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

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

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

Когда вы выбрасываете исключение, вы создаете экземпляр класса 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

Задание

Легко

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

Вы организуете свой код в трех файлах:

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

    Создайте объект Inventory и добавьте новый Product с заданным SKU, названием и начальным количеством 10.

    В зависимости от операции:

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

    При возникновении исключения выведите имя класса исключения, за которым следует ": " и сообщение исключения. Используйте функцию PHP get_class() для получения имени класса.

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

Шпаргалка

В PHP исключения — это объекты, которые сигнализируют об ошибках во время выполнения. Базовым классом является 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;
    }
}

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() — возвращает номер строки, в которой было выброшено исключение

Используйте get_class(), чтобы получить имя класса объекта исключения.

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

<?php

require_once 'Inventory.php';

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

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

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

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

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