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 resetCatch без захвата переменной (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— объект исключения и его методы