W3docs

catch

Ключевое слово catch в PHP перехватывает исключения из блока try и позволяет обработать ошибки без завершения скрипта.

Ключевое слово PHP catch

Когда код внутри блока try встречает исключение — объект, сигнализирующий о том, что что-то пошло не так — выполнение останавливается, и PHP ищет подходящий блок catch для его обработки. Ключевое слово catch указывает тип исключения, которое оно может обработать, и связывает брошенный объект с переменной, чтобы вы могли его изучить. Без catch необработанное исключение становится фатальной ошибкой и останавливает скрипт.

Эта страница объясняет синтаксис catch, как PHP выбирает нужный блок, как читать детали пойманного исключения и типичные паттерны (несколько блоков catch, объединение типов, повторный выброс), которые используются в реальном коде.

Синтаксис

Блок catch всегда следует за блоком try. Он объявляет тип исключения и переменную, которая получает брошенный объект:

<?php

try {
    // Code that may throw an exception
} catch (Exception $e) {
    // Runs only if a matching exception is thrown above
    echo $e->getMessage();
}

PHP сопоставляет блок catch, когда брошенный объект является экземпляром объявленного типа. Поскольку каждое встроенное исключение расширяет базовый класс Exception (и оба расширяют интерфейс Throwable), catch (Exception $e) перехватывает большинство исключений. Перехват Throwable дополнительно захватывает объекты Error, такие как TypeError и DivisionByZeroError.

Вы можете дополнить catch блоком finally, чтобы выполнить код очистки независимо от того, возникло исключение или нет.

Рабочий пример

Функция ниже бросает исключение при попытке деления на ноль. Блок catch перехватывает это исключение и сообщает о нём, не давая скрипту аварийно завершиться:

<?php

function divide($numerator, $denominator)
{
    if ($denominator == 0) {
        throw new InvalidArgumentException("Division by zero.");
    }
    return $numerator / $denominator;
}

try {
    echo divide(10, 0);
} catch (InvalidArgumentException $e) {
    echo "Error: " . $e->getMessage();
}

// Output: Error: Division by zero.

Обратите внимание, что скрипт продолжает выполнение после catch — управление возобновляется на строке, следующей за структурой try/catch, а не прерывается.

Чтение деталей пойманного исключения

Переменная в условии catch ($e выше) — это сам объект исключения. Он предоставляет методы, описывающие произошедшее:

<?php

try {
    throw new RuntimeException("Disk is full", 28);
} catch (RuntimeException $e) {
    echo $e->getMessage();  // Disk is full
    echo "\n";
    echo $e->getCode();     // 28
    echo "\n";
    echo $e->getLine();     // 4  (line where it was thrown)
}
МетодВозвращает
getMessage()Понятное человеку сообщение об ошибке
getCode()Целочисленный код ошибки, переданный конструктору
getFile()Файл, в котором было создано исключение
getLine()Номер строки, где оно было брошено
getTrace()Трассировка стека в виде array
getPrevious()Предыдущее исключение (для цепочки исключений)

Перехват нескольких типов исключений

Когда блок try может завершиться ошибкой разными способами, перечислите несколько блоков catch. PHP проверяет их сверху вниз и выполняет первый подходящий, поэтому размещайте более конкретные типы перед общими:

<?php

try {
    // Code that may throw different exceptions
    throw new InvalidArgumentException("bad input");
} catch (InvalidArgumentException $e) {
    echo "Invalid argument: " . $e->getMessage();
} catch (RuntimeException $e) {
    echo "Runtime problem: " . $e->getMessage();
} catch (Exception $e) {
    echo "Something else: " . $e->getMessage();
}

// Output: Invalid argument: bad input

Если бы catch (Exception $e) стоял первым, он бы поглотил всё, и более конкретные блоки ниже никогда бы не выполнились.

Объединение catch (PHP 7.1+)

Когда два разных типа исключений требуют одинаковой обработки, объедините их с помощью символа | вместо дублирования блока:

<?php

try {
    throw new RuntimeException("connection reset");
} catch (InvalidArgumentException | RuntimeException $e) {
    echo "Handled: " . $e->getMessage();
}

// Output: Handled: connection reset

Catch без захвата переменной (PHP 8.0+)

Если объект исключения не нужен, переменную можно полностью опустить:

<?php

try {
    throw new Exception("ignored details");
} catch (Exception) {
    echo "An error occurred, retrying...";
}

// Output: An error occurred, retrying...

Повторный выброс и цепочка исключений

Иногда блок catch должен записать проблему в журнал, а затем передать её дальше — или обернуть низкоуровневое исключение в более информативное. Передайте оригинал в качестве третьего аргумента конструктора, чтобы сохранить цепочку:

<?php

try {
    try {
        throw new RuntimeException("low-level failure");
    } catch (RuntimeException $e) {
        // Wrap and re-throw with context preserved
        throw new Exception("High-level operation failed", 0, $e);
    }
} catch (Exception $e) {
    echo $e->getMessage();              // High-level operation failed
    echo "\n";
    echo $e->getPrevious()->getMessage(); // low-level failure
}

Лучшие практики

  • Перехватывайте наиболее узкий тип, который можете обработать. Обобщённый catch (Throwable $e) может скрывать ошибки, поглощая программные сбои, которые следовало исправить.
  • Располагайте конкретные типы перед общими. Конкретные подклассы должны предшествовать родительским типам.
  • Не оставляйте catch пустым. Молчаливое игнорирование исключения делает сбои невидимыми; как минимум запишите его в журнал.
  • Бросайте исключения, а не возвращайте флаги ошибок. Комбинируйте catch с throw, чтобы вызывающий код не мог случайно проигнорировать сбои.
  • Используйте finally для очистки (закрытия файлов, снятия блокировок) — код должен выполняться как на пути успеха, так и на пути ошибки.

Связанные темы

  • PHP try — блок, который охраняет catch
  • PHP throw — выброс исключения
  • PHP finally — гарантированный код очистки
  • PHP exception — объект исключения и его методы

Практика

Практика
Что происходит, когда исключение брошено, но не поймано в PHP?
Что происходит, когда исключение брошено, но не поймано в PHP?
Was this page helpful?