Что такое блок finally в PHP?

Ответ

Блок finally — это необязательная часть конструкции try-catch в PHP, которая выполняется всегда, независимо от того, было выброшено исключение или нет. Его основное предназначение — код "очистки" (cleanup), который должен быть выполнен в любом сценарии, например, освобождение ресурсов (закрытие файловых дескрипторов, соединений с БД, снятие блокировок).

Ключевое поведение:

$resource = null;
try {
    $resource = fopen('data.txt', 'r');
    // Чтение данных...
    if (someCondition()) {
        return 'Early Return'; // finally ВСЁ РАВНО выполнится!
    }
    // Другие операции, которые могут выбросить исключение...
} catch (IOException $e) {
    echo "Ошибка ввода-вывода: {$e->getMessage()}";
    throw new RuntimeException('Wrapped', 0, $e); // finally ВСЁ РАВНО выполнится!
} finally {
    // Этот код выполнится в ЛЮБОМ случае:
    // после успешного завершения try, после catch, даже после return или нового throw.
    if ($resource !== null && is_resource($resource)) {
        fclose($resource); // Критически важно закрыть ресурс
        echo "Файл закрыт.n";
    }
}
// Если в finally не было своего return/throw, выполнение продолжится здесь.

Важные нюансы:

  1. Возврат значения: Если в блоке finally есть оператор return, он переопределит любой return из блоков try или catch.
    function test() {
        try {
            return 'from try';
        } finally {
            return 'from finally'; // Это значение будет возвращено функцией!
        }
    }
    echo test(); // Выведет: 'from finally'
  2. Исключения: Если исключение выброшено в finally, оно "затенит" любое исключение, выброшенное ранее в try или catch.
  3. Порядок выполнения: Сначала выполняется try/catch, затем finally, и только потом происходит возврат значения или проброс исключения (если они были определены в try/catch).

Ответ 18+ 🔞

А, блядь, finally! Это же та самая штука, которая всех новичков вводит в ступор, пока они не наступят на грабли. Слушай сюда, сейчас разжую.

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

Вот и в коде так же. Ты открыл файл, подключился к базе, залочил мьютекс — это твоя парилка. Всё пошло по плану? Отлично. Всё пошло по пизде и вылетело исключение? Печально, но факт. А finally — это твой гарантированный душ. Закрыть файл, отключиться от базы, снять лок — это надо сделать всегда. Иначе ресурсы повиснут, и сервер твой скоро будет похож на помойку.

Вот смотри на этот пример, он как раз про файл:

$handle = null;
try {
    $handle = fopen('секреты_соседа.txt', 'r');
    // Читаем, что он там про тебя думает...
    if (узнал_что-то_шокирующее()) {
        return 'Иду жаловаться в полицию!'; // Ранний возврат! Но finally ВСЁ РАВНО сработает!
    }
    // ... остальной код, который может бахнуть исключением
} catch (IOException $e) {
    echo "Бля, файл не читается: {$e->getMessage()}";
    throw new RuntimeException('Заворачиваю ошибку', 0, $e); // Кидаем дальше! Но finally ВСЁ РАВНО сработает!
} finally {
    // А вот это — святое. Выполнится при ЛЮБОМ раскладе:
    // после try, после catch, после return, даже после нового throw.
    if ($handle !== null && is_resource($handle)) {
        fclose($handle); // Закрываем, блять, файл! Это главное!
        echo "Файл закрыт. Сосед ничего не узнает.n";
    }
}
// И только если в finally не было своего return или throw, жизнь пойдёт дальше здесь.

Теперь про две важные, но ебнутые на первый взгляд, особенности. Внимание на хуй!

  1. Кто возвращает значение — тот и главный. Если в finally вдруг написать return, то он затрет собой любой return из try или catch. Это как если бы ты, выходя из душа, решил, что вообще-то ты не из бани, а из космоса вернулся.

    function кто_здесь_главный() {
        try {
            return 'Попытка вернуться из try';
        } finally {
            return 'АХА! Власть захвачена finally!'; // Вернётся именно ЭТО!
        }
    }
    echo кто_здесь_главный(); // Выведет: 'АХА! Власть захвачена finally!'

    Удивление пиздец, да? Но так работает. Доверия к такому коду — ебать ноль, лучше так не делать.

  2. Драка исключений. Если в finally вылетает своё исключение, то оно перебивает то, что летело до него из try или catch. Представь: ты поскользнулся (исключение из try), летишь на пол, но в полёте тебя ещё и вентилятором по ебалу бьёт (исключение из finally). В итоге все запомнят только удар вентилятором. Вот эта, блядь, мартышлюшка.

Итог: finally — это твой надёжный уборщик, твой гарант. Используй его для очистки ресурсов. Но помни — если он начнёт сам возвращать значения или кидать исключения, то может устроить такую хитрую жопу, что потом будешь дебажить до посинения. Э сабака сука, аккуратнее с ним.