# 錯誤處理
當你啟動一個新的 Laravel 項目時,錯誤及異常處理是已為你配置好了的。`App\Exceptions\Handler`類負責記錄應用程序觸發的所有異常并呈現給用戶。在本文檔中,我們將深入探討這個類。
## 配置
你的`config/app.php`配置文件中的`debug`選項決定了對于一個錯誤實際上將顯示多少信息給用戶。默認情況下,該選項的設置將遵照存儲在`.env`文件中的`APP_DEBUG`環境變量的值。
對于本地開發,你應該將`APP_DEBUG`環境變量的值設置為`true`。在生產環境中,該值應始終為`false`。如果在生產中將該值設置為`true`,則可能會將敏感配置值暴露給應用程序的最終用戶。
## 異常處理器
### Report 方法
所有異常都是由`App\Exceptions\Handler`類處理的。這個類包含兩個方法:`report`和`render`。我們將詳細剖析這些方法。`report`方法用于記錄異常或將它們發送給如[Bugsnag](https://bugsnag.com/)或[Sentry](https://github.com/getsentry/sentry-laravel)等外部服務。默認情況下,`report`方法將異常傳遞給記錄異常的基類。不過,你可以任何自己喜歡的方式來記錄異常。
例如,如果你需要以不同方式報告不同類型的異常,則可以使用 PHP 的`instanceof`比較運算符:
~~~php
/**
* 報告或記錄異常
*
* 此處是發送異常給 Sentry、Bugsnag 等外部服務的好位置。
*
* @param \Exception $exception
* @return void
*/
public function report(Exception $exception)
{
if ($exception instanceof CustomException) {
//
}
return parent::report($exception);
}
~~~
> {tip} 不要在`report`方法中進行太多的`instanceof`檢查,而應考慮使用 \[可報告異常(reportable exception) \]((/docs/laravel/5.7/errors#renderable-exceptions)。
#### `Report`輔助函數
有時你可能需要報告異常,但又不希望終止當前請求的處理。`report`輔助函數允許你使用異常處理器的`report`方法在不顯示錯誤頁面的情況下快速報告異常:
~~~php
public function isValid($value)
{
try {
// 驗證值...
} catch (Exception $e) {
report($e);
return false;
}
}
~~~
#### 按類型忽略異常
異常處理器的`$dontReport`屬性包含一組不會被記錄的異常類型。例如,由 404 錯誤導致的異常以及其他幾種類型的錯誤不會寫入日志文件。你可以根據需要添加其他異常類型到此數組中:
~~~php
/**
* 不應被報告的異常類型清單。
*
* @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 響應。默認情況下,異常將傳遞給為你生成響應的基類。不過,你可以按自己意愿檢查異常類型或返回自己的自定義響應:
~~~php
/**
* 將異常l轉換為 HTTP 響應。
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof CustomException) {
return response()->view('errors.custom', [], 500);
}
return parent::render($request, $exception);
}
~~~
### Reportable & Renderable 異常
除了在異常處理器的`report`和`render`方法中檢查異常類型,你還可以直接在自定義異常上定義`report`和`render`方法。當定義了這些方法時,它們會被框架自動調用:
~~~php
<?php
namespace App\Exceptions;
use Exception;
class RenderException extends Exception
{
/**
* 報告異常
*
* @return void
*/
public function report()
{
//
}
/**
* 轉換異常為 HTTP 響應
*
* @param \Illuminate\Http\Request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}
~~~
## HTTP 異常
一些異常用于描述產生自服務器的 HTTP 錯誤代碼。例如,「頁面未找到」錯誤(404),「未經授權的錯誤」(401),甚至可以是開發人員引起的 500 錯誤。 你可以使用`abort`輔助函數從應用程序的任何地方生成這樣的響應:
~~~php
abort(404);
~~~
輔助函數`abort`會立即引發一個由異常處理器渲染的異常。你還可選擇性地提供響應文本:
~~~php
abort(403, 'Unauthorized action.');
~~~
### 自定義 HTTP 錯誤頁面
Laravel 可以輕松顯示各種 HTTP 狀態代碼的自定義錯誤頁面。例如,如果你希望自定義 404 HTTP 狀態碼的錯誤頁面,可以創建一個`resources/views/errors/404.blade.php`視圖文件。該文件將被用于你的應用程序產生的所有 404 錯誤。此目錄中的視圖文件的命名應匹配它們對應的 HTTP 狀態碼。由`abort`函數引發的`HttpException`實例將作為`$exception`變量傳遞給視圖:
~~~php
<h2>{{ $exception->getMessage() }}</h2>
~~~