捕獲異常的場景
通常使用在查詢數(shù)據(jù)庫,調(diào)用第三方接口,支付,隊列,容易出現(xiàn)問題等場景下,出現(xiàn)問題時方便確認問題。
捕獲異常和拋出異常
- 捕獲異常。將業(yè)務(wù)代碼放到try{}代碼塊中,將捕獲這段業(yè)務(wù)代碼中的異常。
try {
//業(yè)務(wù)代碼
} catch (\Exception $exception) {
}
- 拋出異常。當try{}代碼塊中的業(yè)務(wù)代碼出現(xiàn)異常時,我們在catch{}代碼中throw new \Exception($exception->getMessage())來拋出異常。
try {
//業(yè)務(wù)代碼
} catch (\Exception $exception) {
throw new \Exception($exception->getMessage());
}
當異常被拋出時,其后的代碼不會繼續(xù)執(zhí)行,PHP 會嘗試查找匹配的 "catch" 代碼塊。如果捕獲異常了,但未拋出異常,此時代碼會繼續(xù)執(zhí)行,繼續(xù)執(zhí)行的話業(yè)務(wù)邏輯肯定出錯。
需要注意的:捕獲異常和拋出異常永遠是一對的,互相存在的。
我們舉個例子,不拋出異常的代碼如下:
$a = '1a';
$b = '2';
$sum=0;
try {
$sum = $a + $b;
} catch (\Exception $exception) {
Log::info('sum為:' . $exception->getMessage());
// throw new \Exception($exception->getMessage());
}
return $sum;
返回結(jié)果是0,可以看出變量a并不是int型的。由于捕獲到異常但并沒有拋出異常,所以繼續(xù)執(zhí)行了return $sum,返回了0,但我們想要的結(jié)果肯定不是0啊此時就需要拋出異常,代碼如下:
$a = '1a';
$b = '2';
$sum=0;
try {
$sum = $a + $b;
} catch (\Exception $exception) {
Log::info('sum為:' . $exception->getMessage());
throw new \Exception($exception->getMessage());
}
return $sum;
返回結(jié)果httpCode為500,返回錯誤信息為A non well formed numeric value encountered。
APP_DUBUG環(huán)境變量
我們知道代碼拋出異常了之后,返回的500狀態(tài)碼和錯誤信息,在生產(chǎn)環(huán)境中,我們并不希望這些錯誤信息暴露給用戶,在laravel中的環(huán)境變量中有一個為APP_DUBUG,值為false時,表示錯誤信息不展示給用戶。接口報500時,返回如下信息

自定義異常類
我們知道拋出異常后,會報500的錯誤,返回給前端用戶不是很友好。如果我們想把異常轉(zhuǎn)換為將被發(fā)送回瀏覽器的 HTTP 響應,該怎么辦?我們可以自己實現(xiàn)異常類。
- 創(chuàng)建一個異常類,SumException.class
<?php
namespace App\Exceptions;
use Throwable;
class SumException extends \Exception
{
public function __construct(string $message = "", int $code = 0)
{
parent::__construct($message, $code);
}
public function render()
{
return response([
'message' => $this->message,
'code' => $this->code,
], 406);
}
}
- 在代碼中調(diào)用SumException
$a = '1';
$b = '2a';
$sum=0;
try {
$sum = $a + $b;
} catch (\Exception $exception) {
Log::info('sum為:' . $exception->getMessage());
throw new SumException($exception->getMessage(),406);
}
return $sum;
返回結(jié)果為

調(diào)用自己的異常類時,不管環(huán)境變量APP_DUBUG的值為true或false時,都會返回異常信息。
規(guī)范寫法
try {
//業(yè)務(wù)代碼
} catch (\Exception $exception) {
Log::info('error',['message'=>$exception->getMessage()]);
throw new \Exception($exception->getMessage());
}
我們必須要在catch{}中拋出異常,如果不拋出異常,代碼會繼續(xù)執(zhí)行。其次是我們我們在catch{}代碼中要記錄錯誤日志,方便后續(xù)排查問題,其實拋出異常的時候就已經(jīng)記錄錯誤日志了。