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?