Laravelでパスごとにエラービューを出し分ける

Laravelではexceptionのハンドリングを app/Exceptions/Handler.phpで指定できます。
このクラスの実装は大半が親クラスのIlluminate\Foundation\Exceptions\Handlerにあるので、
参考にしながらメソッドをオーバーライドしていきます。

app/Exception/Hander.php
    /**
     * Prepare a response for the given exception.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception $e
     * @return \Symfony\Component\HttpFoundation\Response
     */
    protected function prepareResponse($request, Exception $e)
    {
        if (! $this->isHttpException($e) && config('app.debug')) {
            return $this->toIlluminateResponse(
                $this->convertExceptionToResponse($e), $e
            );
        }

        if (! $this->isHttpException($e)) {
            $e = new HttpException(500, $e->getMessage());
        }

        // パスごとにエラーのviewを分岐する
        return $this->toIlluminateResponse(
            $this->customRenderHttpException($request, $e), $e // ここがparentのものと差し替わっている
        );
    }

    /**
     * parentのrenderHttpExceptionを改変してrequestパスごとに分岐するようにしたもの
     * @param Request $request
     * @param \Symfony\Component\HttpKernel\Exception\HttpException  $e
     * @return \Symfony\Component\HttpFoundation\Response
     */
    private function customRenderHttpException(Request $request, HttpException $e)
    {
        $status = $e->getStatusCode();

        $paths = collect(config('view.paths'));

        view()->replaceNamespace('errors', $paths->map(function ($path) use ($request) {
            return $request->is('admin/*') ? "{$path}/admin/errors" : "{$path}/service/errors"; // viewを分岐
        })->push(__DIR__ . '/views')->all());

        if (view()->exists($view = "errors::{$status}")) {
            return response()->view($view, ['exception' => $e], $status, $e->getHeaders());
        }

        return $this->convertExceptionToResponse($e);
    }

今回はadmin/以下にアクセスが来たときは/views/admin/errorsにそれ以外のときは/views/service/errorsに振り分けます。

親クラスにconvertExceptionToResponseというメソッドがあってそこだけ書き換えられればよかったのですが、パスで分岐するためには\Illuminate\Http\Requestが引数に必要で、それが無かったので、prepareResponseメソッドから書き換えています。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.