Ответ
Блок finally в конструкции try-catch я использую для гарантированного выполнения cleanup-операций независимо от того, как завершился блок try или catch. Это критически важно для предотвращения утечек ресурсов.
Реальный пример работы с транзакциями БД:
$connection = null;
try {
$connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$connection->beginTransaction();
// Бизнес-логика
$stmt = $connection->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->execute([100, 1]);
$stmt = $connection->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->execute([100, 2]);
$connection->commit();
} catch (PDOException $e) {
// Логируем ошибку
error_log("Transaction failed: " . $e->getMessage());
if ($connection) {
$connection->rollBack();
}
throw new ApplicationException("Transfer failed", 0, $e);
} finally {
// Гарантированно закрываем соединение
if ($connection) {
$connection = null;
}
// Освобождаем другие ресурсы
gc_collect_cycles();
}
Ключевое поведение:
finallyвыполняется всегда — после успешногоtry, послеcatch, даже если вcatchестьreturnилиthrow- Порядок выполнения:
try→ (catchесли есть исключение) →finally→ (возврат/проброс если были в catch) - Если в
finallyесть свойreturn, он переопределит возвращаемое значение изtry/catch
Типичные use cases:
- Закрытие файловых дескрипторов (
fclose()) - Освобождение сокетов и сетевых соединений
- Снятие блокировок (локи файлов, мьютексы)
- Сброс флагов и временных состояний
Ответ 18+ 🔞
А, ну вот, опять про этот ваш finally! Ёпта, слушай, это же как золотое правило, блядь: что бы ни случилось — убрать за собой надо. Представь, ты в гостях нажрался как свинья, тарелки по всей квартире, а потом просто свалил. Хозяева потом охуеют, да? Вот и здесь так же.
Смотри, в жизни бывает всякое: код выполнился удачно — красота. Или нихуя не выполнился, вылетело исключение — тоже, в общем-то, ок, мы его поймали. Но ресурсы-то, сука, остались! Соединение к базе висит, файл открыт, память не освобождена. Это ж пиздец просто, утечка будет, сервер рухнет. А finally — это как тот самый адекватный гость, который, даже если его тошнило в хозяйской раковине, всё равно придёт и отмоет всё до блеска. Он выполнится в любом случае. Всегда. Это железно.
Вот смотри на примере, тут всё понятно станет. Допустим, мы бабло переводим со счёта на счёт:
$connection = null;
try {
$connection = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$connection->beginTransaction();
// Снимаем сотку с первого лоха
$stmt = $connection->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?");
$stmt->execute([100, 1]);
// И кидаем её второму
$stmt = $connection->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?");
$stmt->execute([100, 2]);
$connection->commit(); // Всё чики-пуки, коммитим
} catch (PDOException $e) {
// Ой, всё пошло по пизде! Логируем это безобразие
error_log("Transaction failed: " . $e->getMessage());
// И откатываем всё, что натворили, чтобы база не ебнулась
if ($connection) {
$connection->rollBack();
}
// И выбрасываем ошибку дальше, пусть начальство разбирается
throw new ApplicationException("Transfer failed", 0, $e);
} finally {
// А ВОТ ЭТА ЧАСТЬ, БЛЯДЬ, ВЫПОЛНИТСЯ ВСЕГДА!
// Неважно, улетел commit или нас в catch выкинуло.
// Соединение надо прибить. Гарантированно.
if ($connection) {
$connection = null; // Всё, нахуй, закрыли.
}
// И заодно мусор собрать, чисто для души
gc_collect_cycles();
}
Понимаешь, в чём прикол? Порядок-то какой:
- Пытаемся сделать дело в
try. Получилось — молодца. Не получилось — летим вcatch. - В
catchмы можем орать, логировать, даже новую ошибку выкинуть — это всё лирика. - А потом, внезапно, наступает
finally. И он, этот ублюдок, выполняется при любом раскладе. Даже если вcatchу тебя стоитreturnилиthrow— он сначала зайдёт вfinally, сделает свои грязные делишки, а уж потом вернёт или выбросит твоё значение. Хитрая жопа, да?
Хуй с ним, с порядком. Главное — где это применять? Да везде, где есть что закрыть, отключить или почистить!
- Файлы открыл —
fclose()вfinally. - С сокетом поигрался — убивай его там.
- Временную блокировку на файл повесил (
flock()) — обязательно сними вfinally, а то потом весь скрипт встанет колом, и будешь искать, кто же эту хуйню не отпустил. Доверия к таким кодам — ноль ебать.
Одно только предупреждение, ёпта: если ты в самом finally напишешь return, то он перебьёт всё. И то, что вернул try, и то, что собрался вернуть catch. Так что не выёбывайся, используй его только для уборки, а не для бизнес-логики.
Короче, finally — это твой страховочный крюк, гарант порядка. Без него код — распиздяй и смерд пердящий, который после себя говно не убирает.