[ Laravel 5.8 文件 ] 基礎元件 —— 異常處理
簡介
Laravel 預設已經為我們配置好了錯誤和異常處理,我們在App\Exceptions\Handler
類中觸發異常並將響應返回給使用者。在本文件中我們將深入探討這個類。
注:關於 Laravel 異常處理底層原理和實現可以參考學院的這篇教程瞭解更多 ——《深入探討 PHP 錯誤異常處理機制及 Laravel 框架底層的相應實現》
配置
配置檔案config/app.php
中的debug
配置項控制瀏覽器顯示的錯誤資訊數量。預設情況下,該配置項通過.env
檔案中的環境變數APP_DEBUG
進行設定。
對本地開發而言,你應該設定環境變數APP_DEBUG
值為true
。在生產環境,該值應該被設定為false
。如果在生產環境被設定為true
,就有可能將一些敏感的配置值暴露給終端使用者。
異常處理器
所有異常都由類App\Exceptions\Handler
處理,該類包含兩個方法:report
和render
。下面我們詳細闡述這兩個方法。
report 方法
report
方法用於記錄異常並將其傳送給外部服務如Bugsnag
或Sentry
,預設情況下,report
方法只是將異常傳遞給異常被記錄的基類,當然你也可以按自己的需要記錄異常並進行相關處理。
例如,如果你需要以不同方式報告不同型別的異常,可使用 PHP 的instanceof
比較操作符:
/** * 報告或記錄異常 * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param\Exception$e * @return void * @translator laravelacademy.org */ public function report(Exception $e){ if ($e instanceof CustomException) { // } return parent::report($e); }
注:可以考慮使用可報告的異常來取代在reports
方法中進行大量的instanceof
檢查。
全域性日誌上下文
如果當前使用者 ID 可用的話,Laravel 會自動將其新增到每一條異常日誌資訊中作為上下文資料。你也可以通過重寫App\Exceptions\Handler
類的context
方法來定義自己的全域性上下文資料,該資訊會被包含在應用寫入的每一條異常日誌資訊中:
/** * Get the default context variables for logging. * * @return array */ protected function context() { return array_merge(parent::context(), [ 'foo' => 'bar', ]); }
report
輔助函式
有時候你可能需要報告一個異常並繼續處理當前請求。輔助函式report
允許你使用異常處理器的report
方法快速報告一個異常而不會渲染錯誤頁:
public function isValid($value) { try { // Validate the value... } catch (Exception $e) { report($e); return false; } }
通過型別忽略異常
異常處理器的$dontReport
屬性包含一個不會被記錄的異常型別陣列,預設情況下,404 錯誤異常不會被寫到日誌檔案,如果需要的話你可以新增其他異常型別到這個陣列:
/** * 不應該被報告的異常型別列表. * * @var array */ protected $dontReport = [ \Illuminate\Auth\AuthenticationException::class, \Illuminate\Auth\Access\AuthorizationException::class, \Symfony\Component\HttpKernel\Exception\HttpException::class, \Illuminate\Database\Eloquent\ModelNotFoundException::class, \Illuminate\Validation\ValidationException::class, ];
render 方法
render
方法負責將給定異常轉化為傳送給瀏覽器的 HTTP 響應,預設情況下,異常被傳遞給為你生成響應的基類。當然,你也可以按照自己的需要檢查異常型別或者返回自定義響應:
/** * 將異常渲染到HTTP響應中 * * @param\Illuminate\Http\Request$request * @param\Exception$exception * @return \Illuminate\Http\Response */ public function render($request, Exception $exception){ if ($e instanceof CustomException) { return response()->view('errors.custom', [], 500); } return parent::render($request, $exception); }
可報告 & 可渲染的異常
除了在異常處理器的report
和render
方法中進行異常型別檢查外,還可以在自定義異常中直接定義report
和render
方法。當異常中存在這些方法時,框架會自動呼叫它們:
<?php namespace App\Exceptions; use Exception; class RenderException extends Exception { /** * Report the exception. * * @return void */ public function report() { // } /** * Render the exception into an HTTP response. * * @param\Illuminate\Http\Request * @return \Illuminate\Http\Response */ public function render($request) { return response(...); } }
注:你可以在report
方法中注入任何需要的依賴,它們會通過 Laravel服務容器自動解析。
HTTP 異常
有些異常描述來自伺服器的 HTTP 錯誤碼,例如,這可能是一個“頁面未找到”錯誤(404),“認證失敗錯誤”(401)亦或是程式出錯造成的 500 錯誤,為了在應用中生成這樣的響應,可以使用abort
輔助函式:
abort(404);
abort
輔助函式會立即引發一個會被異常處理器渲染的異常,此外,你還可以像這樣提供響應描述:
abort(403, '未授權操作');
該方法可在請求生命週期的任何時間點使用。
自定義 HTTP 錯誤頁面
在 Laravel 中,返回不同 HTTP 狀態碼的錯誤頁面很簡單,例如,如果你想要自定義 404 錯誤頁面,建立一個resources/views/errors/404.blade.php
檔案,該檢視檔案用於渲染程式返回的所有 404 錯誤。需要注意的是,該目錄下的檢視命名應該和相應的 HTTP 狀態碼相匹配。abort
函式觸發的HttpException
異常會以$exception
變數的方式傳遞給檢視:
<h2>{{ $exception->getMessage() }}</h2>
你可以使用 Artisan 命令vendor:publish
釋出 Laravel 的錯誤頁面模板:
php artisan vendor:publish --tag=laravel-errors
模板被髮布後,就可以按照自己的喜好對其進行自定義。