Inertiajs Laravel

Laravel11とInertiajsでカスタムエラーページを作成する方法

本サイトの記事内にアフィリエイト広告が含まれる場合があります。

Laravel11とInertiajsでカスタムエラーページを作成する方法のサムネイル画像

awayuki

音大出身。学生時代はフリーランスでWEB制作・開発しながら、2社で長期エンジニアインターンを経験しました(2年半)。 23卒で、自社開発ベンチャー企業に入社しエンジニア・デザイナーとして働き、2024年1月起業しました! このブログでは、ブログ開設方法・プログラミング・音大からエンジニアになれた方法など書いています。 お仕事依頼はお問い合わせフォームからお問い合わせお願いします。 Zenn

Webアプリケーションを構築する際には、ユーザーエクスペリエンスを損なわないエラーハンドリングが不可欠です。

Laravel 11とInertia.jsを組み合わせて、カスタマイズ可能なエラーページを作成する方法を解説します。

技術構成

  • Laravel11
  • Inertiajs (Vuejs)
  • tailwindcss
  • sail
  • docker

実装すること

Laravelデフォルトのエラーページではなく、自分でカスタマイズしたページを表示する。

なぜエラーページを自作するのか?

HTTPステータスコード、特にユーザーの操作に直接関連するもの(例えば419 'Page Expired')に対して、デフォルトのエラーメッセージではなく、より具体的なユーザーガイダンスを提供することが望ましい場合があるからです。

非エンジニアが、アプリケーションを操作していて、いきなりLaravelのデフォルトのエラーページが表示されたらびっくりしちゃうと思います。

公式ドキュメントを読む

公式ドキュメントには以下のような文章が書かれていました。

Rarely, you may need to customize the entire HTTP response rendered by Laravel's exception handler. To accomplish this, you may register a response customization closure using the respond method:

use Symfony\Component\HttpFoundation\Response;
 
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->respond(function (Response $response) {
        if ($response->getStatusCode() === 419) {
            return back()->with([
                'message' => 'The page expired, please try again.',
            ]);
        }
 
        return $response;
    });
})
https://laravel.com/docs/11.x/errors#customizing-the-exception-response

respondメソッドを使用して、レスポンスのカスタマイズクロージャーを登録するという内容でした。

次に、実際に処理を書いてみます。

Laravel11とInertiajsでカスタムエラーページを作成する方法解説

今まではapp/Exceptions/Handler.php にエラーハンドリングの処理は書いていましたが、Laravel11ではbootstrap/app.php にコードを書く必要がありそうです。

->withExceptions ブロックの中に、以下を足します。

<?php
use Symfony\Component\HttpFoundation\Response;
use Inertia\Inertia;

....省略

->withExceptions(function (Exceptions $exceptions) {
        $exceptions->respond(function (Response $response) {
            if (!app()->environment(['local', 'testing']) && in_array($response->getStatusCode(), [404, 500, 403, 503])) {
                return Inertia::render('Error', [
                    'status' => $response->getStatusCode(),
                ]);
            }
            return $response;
        });
    })

次に、Vueファイルも作成しましょう。

/resources/js/Pages/Error.vue を作成し、以下みたいな感じで書きます。

<script setup>
import ApplicationLogo from "@/Components/ApplicationLogo.vue";
import { computed } from "vue";
import PrimaryButton from "@/Components/PrimaryButton.vue";
import { Link, usePage, Head } from "@inertiajs/vue3";
const props = defineProps({ status: Number });
const title = computed(() => {
  return {
    503: "503 SERVICE UNAVAILABLE",
    500: "500 SERVER ERROR",
    404: "404 NOT FOUND",
    403: "403 FORBIDDEN",
  }[props.status];
});
const description = computed(() => {
  return {
    503: "申し訳ございませんが、現在メンテナンス中です。しばらくお待ちください。",
    500: "サーバーに異常が発生しました。",
    404: "お探しのページは見つかりませんでした。",
    403: "このページへのアクセスは禁止されています。",
  }[props.status];
});
</script>

<template>
  <Head :title="description"/>
  <header
    class="flex flex-wrap justify-center md:flex-nowrap z-[1000] w-full py-4 fixed top-0 left-0 bg-white bg-opacity-60 backdrop-blur-sm"
  >
    <Link
      href="/"
      class="flex-none rounded-xl text-xl inline-block font-semibold focus:outline-none focus:opacity-80"
    >
      <ApplicationLogo
        class="md:w-48 md:h-8 w-30 h-6 fill-current text-gray-500"
      />
    </Link>
  </header>
  <div class="text-zinc-800 mt-36 mb-32 px-6">
    <h1 class="font-medium sm:text-7xl text-4xl text-center">
      {{ title }}
    </h1>
    <p class="text-center font-medium mt-3 sm:text-md text-sm">
      {{ description }}
    </p>
    <div class="flex mt-8 justify-center">
      <Link :href="'/'">
        <PrimaryButton>トップに戻る</PrimaryButton>
      </Link>
    </div>
  </div>
</template>

コードの説明

bootstrap/app.php

  • app()->environment(['local', 'testing']) を使用して、現在のアプリケーションがローカルまたはテスト環境にあるかどうかを確認します。これが false の場合(つまり本番環境の場合)、指定されたステータスコード(404, 500, 403, 503)のいずれかであるかをチェックします。
  • 上記の条件に一致する場合、Inertia::render を使って Error コンポーネントをレンダリングします。この時、エラーステータスコードを status プロパティとしてコンポーネントに渡して、適切なエラー情報を表示します。

resources/js/Pages/Error.vue

  • defineProps を使用して、親コンポーネントから受け取る status プロパティ(HTTPステータスコード)を定義しています。
  • titledescription は計算プロパティで、受け取ったステータスコードに応じてエラータイトルと説明文を返します。

これで、404, 500, 403, 503 の時にエラーページを無事表示することができました 🎉

まだデフォルトのエラーページが表示される方は、本番環境設定になっているかやエラー内容を確認してみてください。

参考URL

  • この記事を書いた人

awayuki

音大出身。学生時代はフリーランスでWEB制作・開発しながら、2社で長期エンジニアインターンを経験しました(2年半)。 23卒で、自社開発ベンチャー企業に入社しエンジニア・デザイナーとして働き、2024年1月起業しました! このブログでは、ブログ開設方法・プログラミング・音大からエンジニアになれた方法など書いています。 お仕事依頼はお問い合わせフォームからお問い合わせお願いします。 Zenn

-Inertiajs, Laravel