'How is the keyword 'finally' meant to be used in PHP?
So, I have been reading about the exceptions today on the PHP online manual, and realize I have yet to understand the purpose or real necessity of the finally keyword. I have read some posts here, so my question is slightly different.
I understand that we can use finally in this way:
function hi(){
return 'Hi';
}
try {
throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
echo $e->getMessage();
}
echo hi();
output:
Fatal error: Uncaught LogicException: Throw Logic in C:\Users\...a.php:167
Stack trace:
#0 {main}
thrown in C:\Users\...a.php on line 167
So, in this case the function hi(); is not being execute and for a good reason. I understand if exception is not handled php interpreter halts the script. good. So far from what I read, finally enables us to execute the function hi(); even if the exception is not handled (even though I don't know why)
So, this one I understand.
try {
throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
echo $e->getMessage();
}finally{
echo hi();
}
output:
Hi
Fatal error: Uncaught LogicException: Throw Logic in C:\Users\...a.php:167
Stack trace:
#0 {main}
thrown in C:\Users\...a.php on line 167
This on should the exception error as well as the 'hi' message from the function, even those I don't know any usage for this. But what I don't undersand this, even if we catch the LogicException with catch (LogicException $e) and no exceptions were thrown still we would see the function being execute, and we would see the 'hi' message. as in this example
try {
throw new LogicException("Throw logic \n");
} catch (LogicException $e) {
echo $e->getMessage();
}finally{
echo hi();
}
outputs
// Throw logic
// Hi
So, we still see the function hi() executed even though we have no Uncaught exceptions. Why and what is the use for this?
I thought the finally block was to be used as a last resort in case the exceptions were not caught, even if that wasn't the case then why is it the use to run it?
Solution 1:[1]
Finally should contain any code which needs to be executed regardless of whether there's an exception or not.
Without finally:
try {
$handle = fopen("file.txt");
//Do stuff
fclose($handle);
return something;
} catch (Exception $e) {
// Log
if (isset($handle) && $handle !== false) {
fclose($handle);
}
}
With finally:
try {
$handle = fopen("file.txt");
return something;
} catch (Exception $e) {
// Log
} finally {
if (isset($handle) && $handle !== false) {
fclose($handle);
}
}
Offers a bit of decluttering in the case that you need to free up a resource after a function has returned.
This becomes even more useful in a case like the following:
try {
$handle = fopen("file.txt");
if (case1) { return result1; }
if (case2) { return result2; }
if (case3) { return result3; }
if (case4) { return result4; }
} finally {
if (isset($handle) && $handle !== false) {
fclose($handle);
}
}
In this case you can reduce all the required fclose calls before each return to a single fclose call that will be executed right before the method returns but after any other code.
Solution 2:[2]
try {
throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
echo $e->getMessage();
}finally{
echo hi(); -> code executed. "Hi" printed out
}
LogicException is here -> Fatal error
so in this case:
try {
throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
echo $e->getMessage();
}finally{
echo hi(); -> code executed
die();
}
no fatal error will be raised, because of die statement and the last variation:
try {
throw new LogicException("Throw logic \n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
echo $e->getMessage();
} catch (LogicException $e) { -> LogicException catched
echo $e->getMessage();
}finally{
echo hi(); -> code executed
}
Solution 3:[3]
I made a little unit test to show how it is working
$a = 'a';
try {
$a .= 'b';
} catch (Exception $ex) {
$a .= 'e';
} finally {
$a .= 'f';
}
$a .= 'x';
$this->assertSame('abfx', $a);
$a = 'a';
try {
$a .= 'b';
throw new Exception();
$a .= '1';
} catch (Exception $ex) {
$a .= 'e';
} finally {
$a .= 'f';
}
$a .= 'x';
$this->assertSame('abefx', $a);
$a = 'a';
try {
try {
$a .= 'b';
throw new Exception();
$a .= '1';
} catch (Exception $ex) {
$a .= 'e';
throw $ex;
$a .= '2';
} finally {
$a .= 'f';
}
$a .= 'x';
} catch (Exception $ex) {
$a .= 'z';
}
$this->assertSame('abefz', $a);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | apokryfos |
| Solution 2 | |
| Solution 3 |
