Классы исключений
Часть раздела Объектно-ориентированное программирование путешествия по 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() сообщают вам, где было выброшено исключение. Использование конкретных типов исключений делает намерения вашего кода более понятными и позволяет более точно обрабатывать ошибки.
Задание
ЛегкоДавайте создадим систему управления запасами, которая использует встроенные классы исключений 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 (это должно вызвать исключение)
При возникновении исключения выведите имя класса исключения, за которым следует
": "и сообщение исключения. Используйте функцию PHPget_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) для получения имени класса
}
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Основы ООП
Внешние файлыВведение в ООПКлассы и объектыКлючевое слово $thisМетодыСвойстваКонструктор (__construct)Деструктор (__destruct)Итоги — Простой калькулятор4Наследование
Основы наследованияКлючевое слово parent::Переопределение методовКлючевое слово finalАбстрактные классыИтоги — Иерархия сотрудников7Инкапсуляция
Public, Protected, PrivateПодробный разбор модификаторов доступаГеттеры и сеттерыСокрытие данныхConstructor Promotion (8.0)Итоги — Система учета студентов10Продвинутые концепции ООП
Композиция против наследованияВнедрение зависимостейАнонимные классыПеречисления (PHP 8.1)Файберы (PHP 8.1)Глубокое погружение в клонирование объектовГенераторы и итераторы13Паттерны проектирования. Часть 2
Паттерн КомандаПаттерн АдаптерПаттерн ДекораторПаттерн Шаблонный методПаттерн СостояниеПаттерн КомпоновщикПаттерн Репозиторий2Пространства имен и автозагрузка
Введение в пространства именКлючевое слово useСтандарт автозагрузки PSR-4Автозагрузчик ComposerИтоги: структурированный проект5Интерфейсы и контракты
Введение в интерфейсыРеализация интерфейсовРеализация нескольких интерфейсовИнтерфейс против абстрактного классаType Hinting с интерфейсамиИтоги — Калькулятор фигур8Магические методы
Введение в магические методы__toString и __debugInfo__get, __set, __isset, __unset__call и __callStatic__clone и клонирование объектов__serialize и __unserializeИтоги — Кастомная коллекция11Система типов и обработка ошибок
Объявление типовNullable-типыТипы объединения и пересеченияКлассы исключенийИерархия пользовательских исключенийTry, Catch, FinallyИтоги — Валидатор форм14Проект: Управление библиотекой
Обзор проектаКлассы Book и User3Свойства классов
Свойства экземпляра и статические свойстваКонстанты в классахСтатические методы и свойстваПриватные и защищенные свойстваСвойства Readonly (PHP 8.1)Итоги — Менеджер банковского счета6Полиморфизм
Снова о переопределении методовПолиморфизм через интерфейсыType Hinting и Union TypesПозднее статическое связываниеИтоги — Payment Processor9Трейты
Введение в трейтыИспользование нескольких трейтовРазрешение конфликтов трейтовАбстрактные методы в трейтахТрейты и наследование12Паттерны проектирования. Часть 1
Введение в паттерны проектированияПаттерн SingletonПаттерн FactoryПаттерн ObserverПаттерн Strategy