Because PHP has a mix of ambiguous low-level errors and higher-level exceptions in its standard library, and the different mechanisms are not well-documented, I took some notes after trying various cases.
This is done in a set_error_handler-free context.
I tested the following cases, even the obvious ones.
- Nothing happening
- Exception thrown
- Warning raised
- Error raised
- Assertion raised
gotoused to jump out of the block
Nothing happening
In case a piece of code in a try block runs just fine, the finally block is properly executed.
try {
$meow = 1 + 2;
} finally {
echo "FINALLY: MEOW\n";
}
Exception thrown
As before, in case anything resembling a Throwable is raised within a try context, the finally block is properly executed.
try {
throw new Error('ERROR: MEOW');
} finally {
echo "FINALLY: MEOW\n";
}
Warning raised
When a method within a try context raises a WARNING of any nature (user or system), the finally block is properly executed.
try {
trigger_error('MEOW MEOW', E_USER_WARNING);
} finally {
echo "FINALLY: MEOW\n";
}
Keep in mind that, by default, a WARNING being raised doesn't interrupt the runtime or the currently run block.
try {
trigger_error('MEOW MEOW', E_USER_WARNING);
// Will be executed
$meow = 1 + 2;
} finally {
echo "FINALLY: MEOW\n";
}
Error raised
When a method within a try context raises an ERROR of any nature (user or system), the finally block is skipped, and the whole runtime stops.
try {
trigger_error('MEOW MEOW', E_USER_ERROR);
} finally {
// Will never be reached
echo "FINALLY: MEOW\n";
}
Assertion raised
When an assertion within a try context fails, the finally block is skipped, and the whole runtime stops.
try {
assert(false);
} finally {
// Will never be reached
echo "FINALLY: MEOW\n";
}
goto used to jump out of the block
As expected of goto, if you use this instruction to jump to an arbitrary location of code outside of the reach of the finally block, it will be skipped.
try {
goto meow;
} finally {
// Will never be reached
echo "FINALLY: MEOW\n";
}
meow:
echo "GOTO: MEOW\n";