15

I'm using try-catch for years, but I never learned how and when to use finally, because I never understood the point of finally (I've read bad books)?

I want to ask you about use of finally in my case.

My code example should explain everything:

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    $s = $c->get_file_content($path);
}

Is this correct use of finally?

More precise question:

Shall I use finally (in future PHP versions or other languages) for handling "create something if it not exists" operations?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kamil
  • 13,363
  • 24
  • 88
  • 183
  • http://stackoverflow.com/questions/927214/how-can-i-get-around-the-lack-of-a-finally-block-in-php – Peter Feb 22 '13 at 19:15
  • 1
    In your case finally might work but I don't think the way you use it is a good practice. You should make all the check necessary before using a function – JudgeProphet Feb 22 '13 at 19:16
  • So to anser your question: "Shall I use finally for handling "create something if it not exists" operations?", I would say no. See below when you may want to use finally. – mika Feb 22 '13 at 19:38
  • No, it's very much not correct. The Finally clause is meant for cleanup such as closing file handles, freeing memory, etc. It's really not meant for retrying the operation. In the event that the original attempt succeeds you end up loading the same data twice, which is very wasteful. – GordonM Jan 12 '17 at 15:30

4 Answers4

31

Finally will always be executed, so in this case, it is not its intended purpose, since normal execution would reopen the file a second time. What you intend to do would be achieved in the same (cleaner) way if you do

$s = "";

$c = MyClassForFileHandling::getInstance();

try
{
    $s = $c->get_file_content($path);
}
catch(FileNotFoundExeption $e)
{
    $c->create_file($path, "text for new file");
    $s = $c->get_file_content($path);
}

Then the manual says:

For the benefit of someone anyone who hasn't come across finally blocks before, the key difference between them and normal code following a try/catch block is that they will be executed even the try/catch block would return control to the calling function.

It might do this if:

  • code if your try block contains an exception type that you don't catch
  • you throw another exception in your catch block
  • your try or catch block calls return

Finally would then be useful in this kind of scenario:

function my_get_file_content($path)
{
    try
    {
        return $c->get_file_content($path);
    }
    catch(FileNotFoundExeption $e)
    {
        $c->create_file($path, "text for new file");
        return $c->get_file_content($path);
    }
    finally
    {
        $c->close_file_handler();
    }
}

=> if you need to make sure you close your file handler in this case, or some resource in general.

7ochem
  • 2,183
  • 1
  • 34
  • 42
mika
  • 1,971
  • 3
  • 18
  • 32
  • 4
    really liked the sense of example. Thanks :) – Mayukh Roy Feb 22 '13 at 19:36
  • 1
    @Kamil Have a closer look: here you have a return statement in the try and catch blocks. Still, finally WILL be executed. – mika Feb 22 '13 at 19:41
  • @mika so thats the difference! Very big thanks. You finally revealed `finally` mystery for me :) – Kamil Feb 22 '13 at 19:45
  • One more thing - when it will be executed? before return? after return? or there are multiple threads involved, and thats why there is no `finally` in PHP? – Kamil Feb 22 '13 at 19:46
  • 2
    @Kamil you are welcome. When return is called, finally will be executed, then return will be performed. No thread involved. – mika Feb 22 '13 at 19:56
4

finally wasn't introduced into PHP until version 5.5 which has not been released yet so that why you haven't seen any examples with it yet. So unless you're running and alpha version of PHP 5.5 you can't use finally yet.

From the manual (exceptions)

In PHP 5.5 and later, a finally block may also be specified after the catch blocks. Code within the finally block will always be executed after the try and catch blocks, regardless of whether an exception has been thrown, and before normal execution resumes.

Example from the manual of using finally

<?php
function inverse($x) {
    if (!$x) {
        throw new Exception('Division by zero.');
    }
    else return 1/$x;
}

try {
    echo inverse(5) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "First finally.\n";
}

try {
    echo inverse(0) . "\n";
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} finally {
    echo "Second finally.\n";
}

// Continue execution
echo 'Hello World';
?>
John Conde
  • 217,595
  • 99
  • 455
  • 496
  • That is right. But the example from OP is kind-of correct (I wonder whether the exception class shouldn't be enclosed in brackets). – Tadeck Feb 22 '13 at 19:14
  • That being said, here's some examples on how to use "finally": https://wiki.php.net/rfc/finally from the wiki and http://athos.blogs.balabit.com/2011/02/try-catch-finally-in-php/ from Athos, that seems nice for you :) – Erenor Paz Feb 22 '13 at 19:16
  • Alpha 5 was released today :) – Mark Baker Feb 22 '13 at 19:17
  • can you pls help me > error > Fatal error: Cannot use try without catch or finally in C:\wamp\www\anusthana\andro.php on line 55 https://justpaste.it/74cqb @john – Gem Oct 23 '18 at 05:37
0

Finally means what do you want to DO Finally.

try
{
    $s = $c->get_file_content($path);
}

catch FileNotFoundExeption
{
    $c->create_file($path, "text for new file");
}

finally
{
    //Create a pdf with my file
    //or, Rename my file
    //or, store my file into Database
}

No matter what happens(regardless of whether an exception has been thrown) inside try or catch, 'Finally code' will execute. So, no point of using same code over 'try' and 'finally'. Does this simply answer your question?

Mayukh Roy
  • 1,815
  • 3
  • 19
  • 31
0

I just want to appoint that if an Exception occurs in the try block, the exception will be correctly raised even if the finally block is present. The usefulness of the finally block is for clean and free resources. I think it's best use is when, for example, you upload a file but then an error happens:

$tmp_name = null;
try {
    $tmp_name = tempnam(UPLOAD_DIR, 'prefix');
    move_uploaded_file($file['tmp_name'], $tmp_name);
    ImageManager::resize($tmp_name, $real_path, $width, $height); // this will rise some exception
}
finally {
    if($tmp_name)
        unlink($tmp_name); // this will ensure the temp file is ALWAYS deleted
}

As you can see, in this way no matter what happen, the temp file will be correctly deleted.
If we would emulate the finally clause in older version of PHP, we should write something like this:

// start finally
catch(Exception $ex) {
}
if($tmp_name)
    unlink($tmp_name);
if( isset($ex) )
    throw $ex;
// end finally

Note that the exception has been re-thrown in case the catch block caught something. It isn't clear as the finally version, but works the same.

Iazel
  • 2,296
  • 19
  • 23