先抛出结论:try内部正常执行try的内部逻辑,异常则执行catch的内部逻辑结构,但是不管执行的哪个都会执行完try catch的内部逻辑(非return)后执行finally的内部逻辑。
如果try catch都有return,按照正常执行,然后执行finally的逻辑,再返回对应的try 或者catch里执行return。
如果try catch finally都有return,执行完finally的逻辑后,会调用finally的return。
示例
public function send(&$msg_entity)
{
$amount = empty($msg_entity['msg_total_price']) ? 0 : $msg_entity['msg_total_price'];
try {
$this->checkMsgEntity($msg_entity);
$this->formatMsgEntity($msg_entity);
if ($this->is_check) { // 只用与校验逻辑
$this->all_msg_entity[] = $msg_entity;
return true;
}
} catch (\Exception $e) {
$this->_log[] = [__METHOD__, ['errmsg' => $e->getMessage(), 'msg_entity' => $msg_entity]];
// 格式错误默认发送成功
return TRUE;
}
$ret = $this->log($msg_entity); // 定制模版可能生成多条记录
$send_status = USERSHORTMSGTPL::SEND_SUCCESS;
try {
if (false == $ret) {
throw new \Exception('添加短信明细记录失败');
}
$msg_entity['log_id'] = $ret;
$amount = $msg_entity['msg_total_price'];
$od_link_id = $msg_entity['oid'];
$b_tr_link_id = $msg_entity['b_tr_link_id'];
list($errno, $errmsg) = $this->companyConsumeEscrow($amount, $od_link_id, $b_tr_link_id);
if ($errno != ERRNO::SUCCESS) {
throw new \Exception($errmsg);
} else {
$send = $this->sendMsgInfo($msg_entity);
if (!$send) throw new \Exception('短信发送失败');
}
return true;
} catch (\Exception $e) {
cmm_log('msg_error=>' . encode_json($msg_entity) . '短信发送失败', 'ERROR_TRACE');
$errmsg = $this->_log[] = $e->getMessage();
$send_status = USERSHORTMSGTPL::SEND_FAIL;
return FALSE;
} finally {
$op_status = $this->updateMsgLogSendStatus($ret, ['send_status' => $send_status, 'send_remark' => $errmsg]);
if ($op_status != ERRNO::SUCCESS) cmm_log('短信发送更新短信明细状态失败', 'ERROR_TRACE');
}
}
代码的执行顺序是:先执行try,抛出异常的话就会运行catch,没有抛出异常的话则不会运行catch,但这两种情况都会finally,并且,finally中的返回值会覆盖掉前面语句的返回值。
finally的意义在于可以处理一些资源的清理和回收等操作。