finally
Ключевое слово "finally" в PHP гарантирует выполнение блока кода после try и catch — независимо от исключений.
Ключевое слово PHP "finally": подробное руководство
Ключевое слово finally является частью синтаксиса обработки исключений PHP. Блок finally прикрепляется к оператору try и гарантированно выполняется после блока try (и любого подходящего блока catch) — независимо от того, успешно ли выполнился код, было ли выброшено Exception, или произошёл ранний возврат. Эта гарантия делает его идеальным местом для очистки: закрытия файлов, освобождения блокировок, завершения транзакций базы данных или записи логов.
На этой странице рассматриваются синтаксис, точный порядок выполнения блоков, взаимодействие finally с return и распространённые паттерны, где он действительно необходим.
Синтаксис
Блок finally прикрепляется к оператору try и выполняется после блоков try и любых блоков catch — независимо от того, было ли выброшено исключение или нет. Вот базовый синтаксис использования ключевого слова finally в PHP:
Синтаксис PHP finally
try {
// code to be executed
} catch (Exception $e) {
// code to handle the exception
} finally {
// code to be executed regardless of whether an exception was thrown or caught
}Блок catch является необязательным при наличии блока finally — конструкция try ... finally (без catch) является допустимым PHP. В этом случае блок finally всё равно выполняется, но любое исключение остаётся неперехваченным и распространяется выше после завершения finally.
Порядок выполнения блоков
Порядок всегда одинаков:
- Выполняется блок
try. - Если выброшено исключение, выполняется первый подходящий блок
catch. Если ни один не подходит, исключение удерживается для повторного выброса. - Выполняется блок
finally— всегда. - Управление покидает оператор (возвращая значение или повторно выбрасывая неперехваченное исключение).
Следующий небольшой скрипт делает порядок наглядным:
<?php
function demo(bool $fail): void
{
try {
echo "1. try\n";
if ($fail) {
throw new Exception("boom");
}
} catch (Exception $e) {
echo "2. catch: {$e->getMessage()}\n";
} finally {
echo "3. finally\n";
}
echo "4. after\n";
}
demo(false);
echo "---\n";
demo(true);
// Output:
// 1. try
// 3. finally
// 4. after
// ---
// 1. try
// 2. catch: boom
// 3. finally
// 4. afterОбратите внимание, что finally выполняется в обоих случаях — один раз без исключения, и один раз после блока catch.
Примеры
Рассмотрим несколько практических примеров использования ключевого слова finally:
Примеры PHP finally
<?php
// Example 1
function divide($a, $b)
{
try {
if ($b == 0) {
throw new Exception("Division by zero.");
}
return $a / $b;
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
} finally {
echo "This code will always be executed.";
}
}
divide(10, 0);
// Output: Error: Division by zero.This code will always be executed.
// Example 2
$file = "example.txt";
$handle = fopen($file, "r");
try {
if (!$handle) {
throw new Exception("Unable to open file.");
}
// code to be executed
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
} finally {
if ($handle !== false) {
fclose($handle);
}
}
// Output: Error: Unable to open file.В этих примерах мы используем ключевое слово finally, чтобы гарантировать последовательное выполнение кода очистки или записи логов.
finally и return
Блок finally выполняется даже если try или catch содержат оператор return. PHP вычисляет возвращаемое значение, затем выполняет finally, и только после этого осуществляет возврат. Если блок finally сам возвращает значение, это значение переопределяет предыдущее — тонкий источник ошибок, поэтому избегайте использования return в finally.
<?php
function withReturn(): string
{
try {
return "from try";
} finally {
echo "finally still runs\n";
}
}
function overriding(): string
{
try {
return "from try";
} finally {
return "from finally"; // overrides the try return
}
}
echo withReturn() . "\n";
echo overriding() . "\n";
// Output:
// finally still runs
// from try
// from finallyТо же правило переопределения применяется к исключениям: если finally выбрасывает исключение, оно заменяет любое исключение или возвращаемое значение, ожидающее выполнения из блоков try/catch.
Преимущества
Использование ключевого слова finally имеет несколько преимуществ:
- Улучшенная обработка ошибок: гарантирует последовательное выполнение кода очистки или записи логов даже при возникновении или обработке исключений.
- Упрощение кода: устраняет необходимость дублировать логику закрытия ресурсов в нескольких блоках
catchили ветках обработки ошибок.
Заключение
Таким образом, ключевое слово finally обеспечивает надёжный способ выполнения кода очистки при обработке исключений — закрытия ресурсов, освобождения блокировок и записи логов — независимо от того, было ли выброшено исключение. Используйте его всегда, когда ресурс, открытый в try, должен быть освобождён в любом случае, и избегайте использования return в блоке finally, чтобы случайно не подавить результат или исключение.
Чтобы углубиться в обработку ошибок PHP, ознакомьтесь с try, catch, классом Exception и общим руководством по исключениям PHP.