How keywod 'finally' is 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?


finally executes every time

regardless of exception or return

exception

One of the more common uses I see is closing a database connection - you want this to happen every time (with or without an exception) so you don't end up with a dangling connection that blocks the database server from accepting new connections.

Consider this pseudo-code:

try {
   $database->execute($sql);
} catch (Exception $exception) {
   $logger->log($exception->getMessage());
   throw $exception;
} finally {
   $database->close();
}

So here we will always close the database connection. If it's a normal query, we close connection after success. If it's an erroneous query, then we still close after the exception has been thrown.

Note that this behavior is different in other languages. For example, in .NET if an exception is thrown/re-thrown from the catch block, then the finally block will not execute.

return

One of the more obscure behaviors is its ability to execute code after a return statement.

Here you can set a variable after the function has returned:

function foo(&$x)
{
    try {
        $x = 'trying';
        return $x;
    } finally {
        $x = 'finally';
    }
}

$bar = 'main';
echo foo($bar) . $bar;

tryingfinally

but an assignment will be what's returned in try:

$bar = foo($bar);
echo $bar . $bar;

tryingtrying

and returning in the finally overrides the return in the try:

function baz()
{
    try {
        return 'trying';
    } finally {
        return 'finally';
    }
}

echo baz();

finally

note this behavior was different in php 5:

finallyfinally
finallyfinally
finally

https://3v4l.org/biO4e


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
}

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.

链接地址: http://www.djcxy.com/p/94768.html

上一篇: browser.explore()与在Prortractor中调试的旧方法

下一篇: keywod'finally'如何在PHP中使用