使用 Laravel 5.5+ 更好的來實現 404 響應

柳公子發表於2019-02-16

譯文首發於 使用 Laravel 5.5+ 更好的來實現 404 響應,轉載請註明出處!

Laravel 5.5.10 封裝了兩個有用的路由器方法,可以幫助我們為使用者提供更好的 404 頁面。現在,當丟擲 404 異常時,Laravel 會顯示一個漂亮的 404.blade.php 檢視檔案,你可以自定義顯示給使用者 UI,但在該檢視中,你無權訪問 sessioncookie,身份驗證(auth)等…

在 laravel 5.5.10 中,我們有一個新的 Route::fallback() 方法,用於定義當沒有其他路由與請求匹配時 Laravel 回退的路由。

Route::fallback(function () {
    return `Sorry` . auth()->user()->name . `! This page does not exist.`;
});

所以,現在我們可以使用具有正常頁面和頁尾的應用佈局,來替代簡單的 404 檢視,同時還能給使用者顯示一條友好的提示資訊。

Route::fallback(function() {
    return response()->view(`notFound`, [], 404);
});
@extends(`layout.app`)

@section(`content`)
    <h3>Sorry! this page doesn`t exist.</h3>
@stop

當 Laravel 渲染這個回退(fallback)路由時,會執行所有的中介軟體,因此當你在 web.php 路由檔案中定義了回退路由時,所有處在 web 中介軟體組的中介軟體都會被執行,這樣我們就可以獲取 session 資料了。

API 介面說明

現在當你點選 /non-existing-page 時,你會看到在回退路由中定義的檢視,甚至當你點選 /api/non-existing-endpoint 時,如果你也不想提供這個介面,你可以到 api 回退路由中定義 JSON 響應,讓我們到 api.php 路由檔案中定義另外一個回退路由:

Route::fallback(function() {
    return response()->json([`message` => `Not Found!]);
});

由於 api 中介軟體組帶有 /api 字首,所有帶有 /api 字首的未定義的路由,都會進入到 api.php 路由檔案中的回退路由,而不是 web.php 路由檔案中所定義的那個。

使用 abort(404) 和 ModelNotFound 異常

當使用 abort(404) 時會丟擲一個 NotFoundHttpException,此時處理器會為我們渲染出 404.blade.php 檢視檔案,同樣的 ModelNotFoundException 異常也會做同樣的處理,那麼我們應該如何如何處理才能在更好的渲染出回退路由的檢視,而不是一個普通的檢視呢?

class Handler extends ExceptionHandler
{
    public function render($request, Exception $exception)
    {
        if ($exception instanceof NotFoundHttpException) {
            return Route::responseWithRoute(`fallback`);
        }

        if ($exception instanceof ModelNotFoundException) {
            return Route::responseWithRoute(`fallback`);
        }

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

Route::respondWithRoute(`fallback`) 回去跑名為 fallback 的路由,我們可以像下面這樣為回退路由命名:

Route::fallback(function() {
    return response()->view(`notFound`, [], 404);
})->name(`fallback`);

甚至,你還可以為特定的資源指定回退路由:

if ($exception instanceof ModelNotFoundException) {
    return $exception->getModel() == Server::class
                ? Route::respondWithRoute(`serverFallback`) 
                : Route::respondWithRoute(`fallback`);
}

現在我們需要在路由檔案中定義這個回退路由:

Route::fallback(function(){
    return `We could not find this server, there are other `. auth()->user()->servers()->count() . ` under your account ......`;
})->name(`serverFallback`);

原文

Better 404 responses using Laravel 5.5+

相關文章