Классы исключений
Часть раздела Объектно-ориентированное программирование путешествия по 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() сообщают, где было выброшено исключение. Использование конкретных типов исключений делает назначение вашего кода более понятным и позволяет выполнять более точную обработку ошибок.
Задание
ЛегкоДавайте создадим систему управления inventory, которая использует встроенные классы исключений PHP для сигнализации о разных типах проблем. Вы создадите inventory продуктов, в которой operation могут завершаться определёнными, понятными способами.
Вы распределите свой код по трём файлам:
Product.php: СоздайтеProductclass, представляющий элемент в 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: СоздайтеInventoryclass, который управляет коллекцией продуктов. Подключите файл 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": CalladdStock(5)для продукта, затем выведите"Stock updated: [quantity]""remove": CallremoveStock(15)для продукта (это должно выбросить exception)"duplicate": Попробуйте добавить another продукт с тем же SKU (это должно выбросить exception)
Когда выбрасывается exception, выведите имя его class, followed by
": ", и message исключения. Используйте PHPget_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), чтобы получить имя класса
}
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Повторение — простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыПовторение — иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateМодификаторы доступа подробноГеттеры и сеттерыСокрытие информацииПродвижение конструктора (8.0)Повторение — система учёта студентов2Пространства имён и автозагрузка
Введение в пространства имёнКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerПовторение — структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс и абстрактный классАннотация типов с интерфейсамиПовторение — калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeПовторение — пользовательская коллекция11Система типов и обработка ошибок
Объявления типовNullable-типыОбъединение и пересечение типовКлассы исключенийПользовательская иерархия исключенийTry, Catch, FinallyПовторение — валидатор формы3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищённые свойстваСвойства только для чтения (PHP 8.1)Повторение — менеджер банковского счёта6Полиморфизм
Повторение переопределения методовПолиморфизм через интерфейсыАннотации типов и объединённые типыПозднее статическое связываниеПовторение — обработчик платежей9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования, часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн StrategyПотренируйтесь самостоятельно: Онлайн-компилятор PHP