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



所以,我一直在阅读PHP在线手册上的异常,并意识到我还没有理解final关键字的目的或真正必要性。我在这里读过一些帖子,所以我的问题略有不同。

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

function hi(){
return 'Hi';
}

try {
throw new LogicException("Throw logic n");
} catch (InvalidArgumentException $e) {
echo $e->getMessage(); 
}
echo 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

因此,在这种情况下,函数hi(;没有被执行,这是有充分理由的。我了解是否未处理异常 PHP 解释器停止脚本。好。到目前为止,与我所读到的相去甚远,最终使我们能够执行函数 hi();便 未处理异常(即使我不知道为什么)

所以,这个我明白了。

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

输出:

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

这应该是异常错误以及来自函数的"hi"消息,即使是那些我不知道任何用法的人。但我不理解这一点,即使我们使用 catch(LogicException $e)捕获LogicException并且没有抛出异常,我们仍然会看到正在执行的函数,并且我们会看到"hi"消息。如本例所示

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

输出

// Throw logic 
// Hi

因此,即使我们没有未捕获的异常,我们仍然看到该函数hi()执行。为什么这样做,有什么用? 我认为最终块将用作最后的手段,以防万一没有捕获异常,即使不是这种情况,那么为什么要运行它呢?

finally

*次执行一次

无论错误、异常甚至return语句如何,finally代码块都将运行。

*如果trycatch块执行die/exit,它将不会运行。

例外

例如,在进程中关闭数据库连接,否则可能会留下阻止数据库服务器接受新连接的悬空连接。

考虑以下伪代码:

try {
$database->execute($sql);
} finally {
$database->close();
}

在这里,我们将始终关闭数据库连接。如果是正常查询,成功后关闭连接,脚本将继续执行。

如果这是一个错误的查询,那么我们仍然会在引发异常后关闭,并且未捕获的异常将冒泡。

下面是catch执行一些日志记录的示例。

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

这将使它关闭连接,无论是否有异常。

返回

其中一个更晦涩的行为是它能够在 return 语句之后执行代码。

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

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

尝试最后

但是作业将是尝试中返回的内容:

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

尝试尝试

在 最终返回 覆盖尝试中的返回:

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

最后

注意此行为在 PHP 5 中是不同的:

最后

最后
最后最后
最后

https://3v4l.org/biO4e

卓越回报

你可以让它看起来像抛出 2 个异常来同时冒泡:

try {
throw new Exception('try');
} finally {
throw new Exception('finally');
}
Fatal error: Uncaught Exception: try in /in/2AYmF:4
Stack trace:
#0 {main}
Next Exception: finally in /in/2AYmF:6
Stack trace:
#0 {main}
thrown in /in/2AYmF on line 6
Process exited with code 255.

https://3v4l.org/2AYmF

但是你无法真正捕捉到我知道的"第一个"异常,以便在运行时做任何有趣的事情:

try {
try {
throw new Exception('try');
} finally {
throw new Exception('finally');
}
} catch (Exception $exception) {
echo 'caught ' . $exception->getMessage();
}

终于被抓住了

https://3v4l.org/Jknpm

*死

如果exitdiefinally块将不会执行。

try {
echo "trying";
die;
} finally {
echo "finally";
}
echo "end";

尝试

https://3v4l.org/pc9oc

†硬件故障

最后,您应该了解,如果有人拔掉您服务器上的电源插头,finally块将不会执行,尽管我尚未对其进行测试,但我希望内存耗尽也会跳过它。

最后,应该包含任何需要执行的代码,无论是否存在异常。

没有最后:

try {
$handle = fopen("file.txt");
//Do stuff
fclose($handle);
return something;
} catch (Exception $e) {
// Log
if (isset($handle) && $handle !== false) {
fclose($handle);
}     
}

最后:

try {
$handle = fopen("file.txt");
return something;
} catch (Exception $e) {
// Log
} finally {
if (isset($handle) && $handle !== false) {
fclose($handle);
}     
}

在函数返回后需要释放资源的情况下提供一些整理。

这在以下情况下变得更加有用:

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);
}    
}

在这种情况下,您可以将每次返回之前所需的所有fclose调用减少为单个fclose调用,该调用将在方法返回之前但在任何其他代码之后执行。

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

所以在这种情况下:

try {
throw new LogicException("Throw logic n"); -> LogicException thrown
} catch (InvalidArgumentException $e) { -> LogicException not catched
echo $e->getMessage(); 
}finally{
echo hi(); -> code executed
die();
}

不会因为 die 语句而引发致命错误 最后一个变体:

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
}

我做了一个小的单元测试来展示它是如何工作的

$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);

相关内容

  • 没有找到相关文章

最新更新