关键字'finally'是如何在PHP中使用的

ʎɹn*_*ɹǝW 18 php oop exception try-catch-finally

所以,我已经在PHP在线手册上阅读了今天的例外情况,并意识到我还没有理解finally关键字的目的或真正的必要性.我在这里看过一些帖子,所以我的问题略有不同.

我知道我们最终可以这样使用:

function hi(){
    return 'Hi';
}


try {
    throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(); 
}

echo hi();
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

所以,在这种情况下函数hi(); 没有被执行,并且有充分的理由.我理解如果没有处理异常,php解释器会暂停脚本.好.到目前为止,我读到的内容,最终使我们能够执行函数hi(); 即使没有处理异常(即使我不知道为什么)

所以,这个我明白了.

try {
    throw new LogicException("Throw logic \n");
} catch (InvalidArgumentException $e) {
    echo $e->getMessage(); 
}finally{
    echo hi();
}
Run Code Online (Sandbox Code Playgroud)

输出:

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
Run Code Online (Sandbox Code Playgroud)

这个应该是异常错误以及来自函数的'hi'消息,即使那些我不知道任何用法.但是我没有强调这一点,即使我们捕获了LogicExceptioncatch (LogicException $e)并且没有异常被抛出,我们仍然会看到函数正在执行,我们会看到'hi'消息.如在这个例子中

try {
    throw new LogicException("Throw logic \n");
} catch (LogicException $e) {
    echo $e->getMessage(); 
}finally{
    echo hi();
}
Run Code Online (Sandbox Code Playgroud)

输出

// Throw logic 
// Hi
Run Code Online (Sandbox Code Playgroud)

因此,hi()即使我们没有未捕获的异常,我们仍然会看到该函数已执行.为什么以及它的用途是什么?我认为finally块是作为最后的手段,以防异常没有被捕获,即使不是这种情况,那么为什么运行它的用途呢?

Jef*_*ett 27

finally每次执行

无论例外还是退货

例外

我看到的一个更常见的用途是关闭数据库连接 - 您希望每次都发生这种情况(有或没有异常),因此您最终不会有阻止数据库服务器接受新连接的悬空连接.

考虑这个伪代码:

try {
   $database->execute($sql);
} finally {
   $database->close();
}
Run Code Online (Sandbox Code Playgroud)

在这里,我们将始终关闭数据库连接.如果是普通查询,我们会在成功后关闭连接.如果这是一个错误的查询,那么我们仍然会在抛出异常后关闭.

这是一个catch做一些日志记录的例子.

try {
   $database->execute($sql);
} catch (Exception $exception) {
   $logger->error($exception->getMessage(), ['sql' => $sql]);
   throw $exception;
} finally {
   $database->close();
}
Run Code Online (Sandbox Code Playgroud)

这将使其在有或没有异常的情况下关闭连接.

请注意,此行为在其他语言中有所不同.例如,在.NET中,如果从catch块抛出/重新抛出异常,则finally块将不会执行.

返回

其中一个比较模糊的行为是它在返回语句后执行代码的能力.

在这里你可以在函数返回后设置一个变量:

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

$bar = 'main';
echo foo($bar) . $bar;
Run Code Online (Sandbox Code Playgroud)

tryingfinally

但是一项任务将在try中返回:

$bar = foo($bar);
echo $bar . $bar;
Run Code Online (Sandbox Code Playgroud)

tryingtrying

并在最后返回覆盖try中的返回:

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

echo baz();
Run Code Online (Sandbox Code Playgroud)

最后

注意这个行为在php 5中有所不同:

finallyfinally
finallyfinally
最后

https://3v4l.org/biO4e

  • @mvrht:当然你可以在`throw`statement _without_之前使用`finally`关闭数据库连接,但重点在于:首先,也许你没有捕获_every_ exception但只是某种类型,那么你就不要没有达到`close()`调用其他异常.其次,即使你确实捕获了每个异常,那么你需要在某处(在`try`block结尾或在`catch`块之后)重复一行代码来调用`close()`.将该调用放在`finally`块中,你只需要编写一次它就会在每种情况下执行它(如果异常发生或不发生,如果它被捕获或不捕获). (3认同)
  • @詹姆斯,我们必须是同一个人,因为无论我看到它,_也_都会让我发疯,所以我故意把它留下来,让它成为一个混蛋。但我现在意识到我的方式不成熟,并添加了两个适当的参考文献⛪ (2认同)