Try, Catch, Finally
Часть раздела Объектно-ориентированное программирование путешествия по PHP на Coddy — урок 68 из 91.
Теперь, когда вы знаете, как создавать и выбрасывать исключения, вам нужно научиться тому, как перехватывать их. Структура try-catch-finally позволяет вам корректно обрабатывать исключения вместо того, чтобы позволять им приводить к сбою вашего приложения.
Оберните код, который может вызвать исключение, в блок try, а затем обработайте исключение в блоке catch:
<?php
class Calculator {
public function divide(int $a, int $b): float {
if ($b === 0) {
throw new InvalidArgumentException("Cannot divide by zero");
}
return $a / $b;
}
}
$calc = new Calculator();
try {
echo $calc->divide(10, 0);
} catch (InvalidArgumentException $e) {
echo "Error: " . $e->getMessage();
}
Результат:
Error: Cannot divide by zeroВы можете перехватывать различные типы исключений с помощью нескольких блоков catch. PHP проверяет их по порядку, поэтому сначала указывайте более специфичные исключения:
<?php
try {
// рискованный код
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
echo "Something went wrong: " . $e->getMessage();
}
Блок finally выполняется независимо от того, было ли выброшено или перехвачено исключение. Он идеально подходит для задач по очистке, таких как закрытие соединений:
<?php
try {
echo "Attempting operation\n";
throw new Exception("Failed");
} catch (Exception $e) {
echo "Caught: " . $e->getMessage() . "\n";
} finally {
echo "Cleanup complete";
}
Вывод:
Attempting operation
Caught: Failed
Cleanup completeБлок finally выполняется даже в том случае, если вы выполняете возврат из блоков try или catch, что делает его надежным инструментом для выполнения необходимых операций по очистке.
Задание
ЛегкоДавайте создадим систему обработки файлов, которая демонстрирует, как try-catch-finally работают вместе для корректной обработки ошибок, гарантируя при этом обязательное выполнение очистки ресурсов.
Вы организуете свой код в трех файлах:
FileException.php— Создайте пользовательский классFileException, который расширяетException. Он будет представлять ошибки, связанные с файлами в вашей системе.FileProcessor.php— Создайте классFileProcessor, который имитирует операции с файлами. Подключите файл FileException. Ваш класс должен иметь:- Приватное булево свойство
$isOpen, инициализированное какfalse - Метод
open(string $filename): void, который устанавливает$isOpenвtrueи выводит"Opening: [filename]". Если имя файла —"invalid.txt", выбросьте исключениеFileExceptionс сообщением"Cannot open file" - Метод
process(): void, который выводит"Processing file...". Если$isOpenравноfalse, выбросьте исключениеRuntimeExceptionс сообщением"File not open" - Метод
close(): void, который устанавливает$isOpenвfalseи выводит"File closed" - Метод
isOpen(): bool, который возвращает текущее состояние
- Приватное булево свойство
main.php— Подключите файл FileProcessor. Вы получите один входной параметр: имя файла.Создайте объект
FileProcessorи используйте структуруtry-catch-finally, чтобы:- В блоке
try: вызватьopen()с именем файла, затем вызватьprocess() - Сначала перехватить
FileExceptionи вывести"File error: [message]" - Перехватить
RuntimeExceptionи вывести"Runtime error: [message]" - В блоке
finally: проверить, открыт ли файл с помощьюisOpen(), и если да, вызватьclose(). Затем вывести"Cleanup complete"
- В блоке
Блок finally гарантирует, что очистка произойдет независимо от того, завершились ли операции успешно или с ошибкой. Этот паттерн важен для управления такими ресурсами, как файлы, соединения с базой данных или сетевые сокеты, где очистка должна выполняться независимо от того, что происходит во время обработки.
Шпаргалка
Используйте try-catch-finally для корректной обработки исключений и гарантии того, что код очистки выполнится в любом случае:
<?php
try {
// код, который может выбросить исключение
} catch (ExceptionType $e) {
// обработка исключения
echo $e->getMessage();
}
Перехватывайте несколько типов исключений с помощью отдельных блоков catch. Сначала указывайте более специфичные исключения:
<?php
try {
// рискованный код
} catch (InvalidArgumentException $e) {
echo "Bad input: " . $e->getMessage();
} catch (Exception $e) {
echo "Something went wrong: " . $e->getMessage();
}
Блок finally выполняется независимо от того, было ли выброшено или перехвачено исключение, что делает его идеальным для операций очистки:
<?php
try {
// попытка выполнения операции
} catch (Exception $e) {
// обработка ошибки
} finally {
// код очистки выполняется всегда
}
Попробуйте сами
<?php
require_once 'FileProcessor.php';
// Чтение входных данных
$filename = trim(fgets(STDIN));
// TODO: Создать экземпляр FileProcessor
// TODO: Использовать структуру try-catch-finally:
// - В блоке try: вызвать open() с именем файла, затем вызвать process()
// - Сначала перехватить FileException и вывести "File error: [message]"
// - Перехватить RuntimeException и вывести "Runtime error: [message]"
// - В блоке finally: проверить, открыт ли файл с помощью isOpen(), если да, вызвать close()
// Затем вывести "Cleanup complete"
?>В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
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