A finally block runs no matter what happens in the try: success, an exception, or even a return. It is the right place for cleanup.
<?php
function work(bool $fail): void
{
try {
echo "Start\n";
if ($fail) {
throw new RuntimeException("boom");
}
echo "Done\n";
} catch (RuntimeException $e) {
echo "Caught: " . $e->getMessage() . "\n";
} finally {
echo "Cleanup\n";
}
}
work(false);
echo "---\n";
work(true);
Start
Done
Cleanup
---
Start
Caught: boom
Cleanup
Cleanup is printed in both cases.
A typical use: close what you opened
<?php
$handle = fopen("data.txt", "w");
try {
fwrite($handle, "important data");
throw new RuntimeException("something went wrong while writing");
} catch (RuntimeException $e) {
echo "Error: " . $e->getMessage() . "\n";
} finally {
fclose($handle);
echo "File closed";
}
Error: something went wrong while writing
File closed
Without finally, an exception could skip fclose() and leave the file open.
try and finally without catch
You can use finally alone. The exception still travels upward, but the cleanup runs first.
<?php
function risky(): void
{
try {
throw new LogicException("not handled here");
} finally {
echo "Cleaning up\n";
}
}
try {
risky();
} catch (LogicException $e) {
echo "Caught outside: " . $e->getMessage();
}
Cleaning up
Caught outside: not handled here
finally and return
finally runs even when the try has already hit return.
<?php
function test(): string
{
try {
return "from try";
} finally {
echo "finally runs first\n";
}
}
echo test();
finally runs first
from try
A return inside finally wins
finally itself contains return, it replaces the earlier return and swallows exceptions. Avoid return and throw inside finally unless you are sure.Common uses
- Close files, database connections or locks.
- Release a lock (
flock($h, LOCK_UN)). - Roll back a database transaction when something fails.
- Remove temporary files.
<?php
$lock = fopen("job.lock", "c");
flock($lock, LOCK_EX);
try {
echo "Doing exclusive work\n";
} finally {
flock($lock, LOCK_UN);
fclose($lock);
}
Doing exclusive work
Not every cleanup needs finally
finally when cleanup matters before the script ends, such as locks and transactions.