PHP: Notes on `finally` Published the 2021-03-30 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 - `goto` used 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. ```php 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. ```php 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. ```php 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. ```php 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. ```php 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. ```php 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. ```php try { goto meow; } finally { // Will never be reached echo "FINALLY: MEOW\n"; } meow: echo "GOTO: MEOW\n"; ```