PHP finally
时间:2025-5-12 15:11 作者:wanzi 分类: php
我以为我理解try ... catch ...finally 中finally ,但是我死去的学习记忆还有死倔的特质让我造成了线上致命bug
事故现场
朋友找我说:“你的登录接口怎么一直是用户名或密码错误”,把我搞懵了,幸亏这是个人的产品。我休息了片刻去调试,发现确实如此,然后在那里耽误了半个小时才改好。
一开始我的代码是:
try {
if (!$user) {
return $this->fail('用户名或密码错误');
}
$result = $this->authService->login($authDto);
return $this->success('授权成功')
} catch (\Throwe $e) {
Logger::error("[授权失败]用户xxx在xx设备授权失败,原因:{$e->getMessage()}");
return $this->fail('用户名或密码错误');
}
然后我又改了:
// ...
try {
if ($user) {
$result = $this->authService->login($authDto);
return $this->success('授权成功')
}
} catch (\Throwe $e) {
Logger::error("[授权失败]用户xxx在xx设备授权失败,原因:{$e->getMessage()}");
//return $this->fail('用户名或密码错误');
} finally {
return $this->fail('用户名或密码错误');
}
改过的代码后,我也没测了,因为没改之前测试过了,内心笃定了finally的理解。结果我错了,现在想来我有去注意这个finally的含义和作用吗?好像n年前有看过鸟哥的网站介绍又好像没有看过。
finally解说
在 PHP 中使用 try ... catch ... finally 结构时,即使在 try 或 catch 块中执行了 return,finally 块中的代码仍然会执行 。
这是 PHP(以及 Java、C# 等语言)设计的一个特性:
finally 块总会被执行(除非程序提前终止,如 exit() 或崩溃),不管是否发生了异常或是否有 return 语句。
示例说明:
function test() {
try {
echo "In try\n";
return "Returned from try\n";
} catch (Exception $e) {
echo "In catch\n";
} finally {
echo "In finally\n";
}
}
echo test();
输出结果:
In try
In finally
Returned from try
为什么这样设计?
finally 的目的是用来做资源清理 的工作,比如关闭文件、数据库连接、释放锁等。无论函数是否提前返回或者抛出异常,这些资源都应该被正确释放。
function readFile($filename) {
$handle = fopen($filename, 'r');
try {
$content = fread($handle, filesize($filename));
return $content;
} finally {
fclose($handle);
echo "File handle closed.\n";
}
}
即使读取文件后立即 return,也要确保 fclose 被调用。
特殊情况注意:
如果 finally 中也包含 return,那么它将覆盖 try 或 catch 中的返回值:
function test() {
try {
return "from try";
} finally {
return "from finally";
}
}
echo test(); // 输出: from finally
所以要注意:finally 中的 return 会覆盖前面的返回值。