Laravel 中的異常處理


PS - 個人博客原文:Laravel 中的異常處理

這篇文章里,我們將研究 Laravel 框架中最重要也最少被討論的功能 —— 異常處理。

Laravel 自帶了一個異常處理類,它能夠讓你以簡單、優雅的方式 report 和 render 異常。

文章的前半部分,我們將研究異常處理類(exception handler)提供的默認配置,然后研究異常處理類,並借此理解 Laravel 框架處理異常的過程。

文章的后半部分,我們將創建一個自定義的異常處理類,用於捕獲自定義的異常。

異常處理類

首先,我們看一下與異常相關的配置,打開 config/app.php 文件,找到下面這個片段:

...
...
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/

'debug' => env('APP_DEBUG', false),
...
...

正如注釋中所說,debug 設置為 true 時,會顯示詳細的調試錯誤信息,設置為 false 時,只顯示簡單的錯誤信息。這個變量的默認值是通過 .env 文件中的 APP_DEBUG 環境變量設置的。

在開發環境下,你應該將其設置為 true,這樣開發時更容易發現錯誤並修復它們。在生產環境下應該設置為 false,只顯示簡單的信息。

除了顯示錯誤,你還可以將錯誤記錄到日志文件中。打開配置文件 config/app.php,找到下面這行代碼:

...
...
'log' => env('APP_LOG', 'single'),

'log_level' => env('APP_LOG_LEVEL', 'debug'),
...
...

日志文件默認路徑為:storage/logs/laravel.log,大部分場景下它已經夠用了。APP_LOG_LEVEL決定了錯誤日志被記錄的級別。

上面就是關於異常和日志相關的配置的基本介紹。

然后,我們看一下 Laravel 自帶的默認異常處理類。打開 app/Exceptions/Handler.php 文件:

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @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\Session\TokenMismatchException::class,
        \Illuminate\Validation\ValidationException::class,
    ];

    /**
     * Report or log an exception.
     *
     * This is a great spot to send exceptions to Sentry, Bugsnag, etc.
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }
 
    /**
     * Convert an authentication exception into an unauthenticated response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Auth\AuthenticationException  $exception
     * @return \Illuminate\Http\Response
     */
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        return redirect()->guest(route('login'));
    }
}

這里有兩個重要的方法:report()render()

report() 方法用於將異常報告給外部服務或者記錄日志,默認情況下,將異常傳遞給記錄異常的基類。注意對於添加到 dontReport 屬性數組中的異常類,則不會被報告(執行此方法)。

render() 方法負責將給定的異常轉換為將被發送回瀏覽器的 HTTP 響應。默認情況下,異常將傳遞給為你生成響應的基類。你可以在這里針對不同的異常,自定義相應的響應。

最后,提供了一個 unauthenticated() 方法用於處理 AuthenticationException 異常,能夠讓你決定未認證時用戶能夠看到的信息。

自定義異常

下面我們創建一個自定義異常類來處理 CustomException 類型的異常。這個自定義異常類背后的原則同時支持異常管理和自定義異常信息的輸出。

我們創建一個異常類文件app/Exceptions/CustomException.php

<?php
 
namespace App\Exceptions;
 
use Exception;
 
class CustomException 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()->view(
                'errors.custom',
                array(
                    'exception' => $this
                )
        );
    }
}

注意到,CustomException 擴展自 Exception 類。出於演示目的,我們只討論 render() 方法,當然你也可以自定義 report() 方法。

上面的 render() 中,我們將顯示 errors.custom 頁面給用戶。通過這種方式,你可以為自己的異常自定義頁面輸出。

當然,我們還要創建一個相關聯的視圖文件 resources/views/errors/custom.blade.php

Exception details: <b>{{ $exception->getMessage() }}</b>

要想上面的代碼執行,我們還需要修改 app/Exceptions/Handler.php 中的 render() 方法:

...
...
/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof \App\Exceptions\CustomException)  {
        return $exception->render($request);
    }

    return parent::render($request, $exception);
}
...
...

在這里,我們先檢查異常類型,然后調用我們自己的異常的 render() 方法從而實現輸出。

所有到此所有的就介紹完了。

讓我們繼續,創建一個控制器 app/Http/Controllers/ExceptionController.php 來測試我們寫的自定義異常類:

<?php
namespace App\Http\Controllers;
 
use App\Http\Controllers\Controller;
 
class ExceptionController extends Controller
{
    public function index()
    {
        // something went wrong and you want to throw CustomException
        throw new \App\Exceptions\CustomException('Something Went Wrong.');
    }
}

然后在 routes/web.php 中添加一個路由:

// Exception routes
Route::get('exception/index', 'ExceptionController@index');

然后訪問 http://your-laravel-site.com/exception/index , 最終應當輸出 errors.custom 視圖。

所以以上就是 Laravel 處理異常的過程,希望你會喜歡。

本文翻譯自,部分有所改動。
原文鏈接:https://code.tutsplus.com/tutorials/exception-handling-in-laravel--cms-30210


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM