Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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';
?>

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?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top