W3docs

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.

Порядок выполнения блоков

Порядок всегда одинаков:

  1. Выполняется блок try.
  2. Если выброшено исключение, выполняется первый подходящий блок catch. Если ни один не подходит, исключение удерживается для повторного выброса.
  3. Выполняется блок finally — всегда.
  4. Управление покидает оператор (возвращая значение или повторно выбрасывая неперехваченное исключение).

Следующий небольшой скрипт делает порядок наглядным:

<?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.

Практика

Практика
Какие утверждения верны относительно ключевого слова 'finally' в PHP?
Какие утверждения верны относительно ключевого слова 'finally' в PHP?
Was this page helpful?