Menu
Coddy logo textTech

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, что делает его надежным инструментом для выполнения необходимых операций по очистке.

challenge icon

Задание

Легко

Давайте создадим систему обработки файлов, которая демонстрирует, как 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"

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

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

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