當你開始一個新的 Laravel 項目時,它已經配置了錯誤和異常處理機制。 App\Exceptions\Handler 類別用於記錄應用觸發的所有異常,然後將其呈現給用戶。我們將在本章節深入討論這個類別
config/app.php 設定檔案中的 debug 選項決定了對於一個錯誤實際上將顯示多少訊息給用戶。預設情況下,該選項的設置將按照在 .env 檔案中的 APP_DEBUG 環境變數的值
對於本地開發,你應該將 APP_DEBUG 環境變數的值設置為 true。在正式環境中,該值應始終為 false。如果在正式環境中將該值設置為 true,可能會將敏感設定值暴露給應用的用戶
所有異常都是由 App\Exceptions\Handler 類別處理。此類包含一個 register() ,可以在其中註冊自定義異常報告程序和渲染器回呼。本文將詳細說明每個概念。異常報告用於記錄異常或將其發送到如 Flare、Bugsnag 或 Sentry 等外部服務。預設情況下,將根據你的日誌配置來記錄異常。不過你可以用自己喜歡的方式來記錄異常
例如,如果您需要使用不同的方式來報告不同的異常,可以使用 reportable() 來註冊一個 Closure,當需要報告指定的異常的時候便會執行它。 Laravel 將通過檢查 Closure 的型別提示來判斷 Closure 報告的異常類型
use App\Exceptions\InvalidOrderException;
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (InvalidOrderException $e) {
//
});
}
當使用 reportable() 註冊一個自定義異常報告回呼函式時, Laravel 依然會使用預設的日誌配置記錄下應用異常。 如果您想要在預設的日誌堆疊中停止這個行為,可以在定義報告回呼時使用 stop()
$this->reportable(function (InvalidOrderException $e) {
//
})->stop();
$this->reportable(function (InvalidOrderException $e) {
return false;
});
技巧:
要為指定的異常自定義異常報告,可以使用可報告異常
在可用的情況下, Laravel 會自動將當前用戶的編號作為資料添加到每一條異常日誌資料中。你可以通過複寫 App\Exceptions\Handler 類別中的 context() 來定義您自己的全域 Context(環境變數),此後每一條異常日誌訊息都將包含這個訊息
/**
* Get the default context variables for logging.
*
* @return array
*/
protected function context()
{
return array_merge(parent::context(), [
'foo' => 'bar',
]);
}
有時你可能需要報告異常,但不終止當前請求的處理。 report() 幫助函數允許你在不渲染錯誤頁面給用戶的情況下快速報告異常:
public function isValid($value)
{
try {
// Validate the value...
} catch (Throwable $e) {
report($e);
return false;
}
}
當建立應用時,常會有些類型的異常是你想要忽略掉而不需要報告的。應用的異常處理器的 $dontReport 屬性包含了一個不會被日誌記錄的異常類型的陣列,它預設是一個空陣列,任何類別被加到這個陣列後將不會被回報。比方說由 404 錯誤導致的錯誤就不會被寫到日誌中,你可以根據需要添加其他異常類型到該陣列中
use App\Exceptions\InvalidOrderException;
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
InvalidOrderException::class,
];
在背後, Laravel 已經為你忽略了一些類型的錯誤,比方說 404 的 HTTP not found 錯誤,或者是由無效的 CSRF tokens 所造成的 419 HTTP 回應等
預設情況下, Laravel 異常處理器會自動為你轉換異常為 HTTP 回應。你當然也可以在異常處理器的 renderable() 中註冊一個特定類型的異常的自定義渲染 Closure 來實現。
傳給 renderable() 的 Closure 應該要回傳一個 Illuminate\Http\Response 實例,它將會經由 response() 來生成。 Laravel 將會根據 Closure 的型別提示來確定異常的類別:
use App\Exceptions\InvalidOrderException;
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->renderable(function (InvalidOrderException $e, $request) {
return response()->view('errors.invalid-order', [], 500);
});
}
除了在異常處理器的 report 和 render 方法中檢查異常類型外,你也可以直接在自定義異常中定義 report 和 render 方法。當定義了這些方法之後它們將被框架自動呼叫
<?php
namespace App\Exceptions;
use Exception;
class InvalidOrderException extends Exception
{
/**
* Report the exception.
*
* @return void
*/
public function report()
{
//
}
/**
* Render the exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function render($request)
{
return response(...);
}
}
如果您的異常包含了僅在滿足某些條件時才報告的自定義報告邏輯,您可能需要指示 Laravel 在某些狀況下只使用預設的異常處理配置去報告它。你可以在異常的 report() 中回傳 false 來達成:
/**
* Report the exception.
*
* @return bool|void
*/
public function report()
{
// Determine if the exception needs custom reporting...
return false;
}
技巧:
你可以通過型別提示傳遞任意的依賴到 report() 中,它們將被 Laravel 的服務容器自動注入到方法中
某些錯誤碼描述了服務器的 HTTP 錯誤原因。例如,錯誤404代表「頁面未找到」,錯誤401代表「未經授權的錯誤」甚至是開發者造成的 500 內部錯誤。要在應用的任何地方生成這樣的回應,可以使用 abort() 幫助函式
abort(404);
Laravel 創建了可以輕鬆顯示各種 HTTP 狀態碼的自定義錯誤頁面。例如如果您想要自定義 HTTP 狀態碼為 404 的錯誤頁面,您只需創建 resources/views/errors/404.blade.php 檔案。該檔案用於應用產生的所有 404 錯誤。errors資料夾中的視圖名稱應為它們所對應的 HTTP 狀態碼。由 abort() 引發的 HttpException 實例將作為 $exception 變數傳遞給視圖:
<h2>{{ $exception->getMessage() }}</h2>
你可以使用 vendor:publish 這一個 Artisan 命令來發布 Laravel 錯誤頁面模板到專案中。一旦你發布了模板,你就可以根據需要來自定義它們
php artisan vendor:publish --tag=laravel-errors
or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing