カテゴリ: Laravel 更新日: 2026/03/14

LaravelでAPI用のJSONエラーレスポンスを整形する方法!初心者向け完全ガイド

LaravelでAPI用に例外レスポンスを整形する方法(JSONエラー処理)
LaravelでAPI用に例外レスポンスを整形する方法(JSONエラー処理)

先生と生徒の会話形式で理解しよう

生徒

「LaravelでAPIを作っているのですが、エラーが起きたときのレスポンスをJSON形式で返すにはどうすればいいですか?」

先生

「APIのエラー処理は、Webページとは少し違う考え方が必要です。Handler.phpを使ってJSONで整形されたエラーレスポンスを返す方法を一緒に学びましょう。」

生徒

「JSONってよく聞くんですが、そもそも何ですか?」

先生

「JSONはデータをやり取りするときに使う書き方のルールです。基本から順番に説明していきますよ!」

1. APIとJSONエラー処理の基本を理解しよう

1. APIとJSONエラー処理の基本を理解しよう
1. APIとJSONエラー処理の基本を理解しよう

まずAPIという言葉から説明します。APIとは「Application Programming Interface」の略で、異なるシステム同士がデータをやり取りするための窓口のようなものです。たとえばスマートフォンのアプリが天気情報を表示するとき、天気データを提供するサーバーにAPIを通じてデータを取りに行っています。

そしてJSONとは「JavaScript Object Notation」の略で、データを整理して書くためのフォーマット(書き方のルール)です。人間にも読みやすく、機械にも処理しやすい形式として、現在のWeb開発では非常に広く使われています。たとえばユーザー情報をJSONで表すと、{"name": "田中太郎", "age": 25}のような形になります。

Laravelを使ってAPIを作る場合、エラーが発生したときにHTMLのエラーページを返してしまうと、アプリ側でそのデータを受け取って処理することができません。そのためエラーのときもJSON形式でレスポンス(返答)を返す必要があります。この仕組みを正しく整えることが、使いやすいAPIを作るための重要なポイントです。

2. LaravelがAPIリクエストを判定する仕組み

2. LaravelがAPIリクエストを判定する仕組み
2. LaravelがAPIリクエストを判定する仕組み

Laravelには、届いたリクエスト(アクセス)がAPIからのものかどうかを自動で判定する仕組みが備わっています。リクエストのURLが/api/から始まっている場合や、リクエストヘッダーにAccept: application/jsonが含まれている場合、LaravelはそのリクエストをAPI向けと判断してJSONでレスポンスを返そうとします。

リクエストヘッダーとは、アクセスするときに一緒に送られる付属情報のようなものです。手紙でいえば封筒に書かれた「宛先」や「差出人」にあたる部分です。Accept: application/jsonは「JSON形式のデータを受け取りたい」という意味の指示です。

この判定はLaravelが自動でやってくれるため、開発者は意識せずにAPIとWebページの両方に対応したエラー処理を書くことができます。ただし、より細かいカスタマイズをしたい場合はapp/Exceptions/Handler.phpを編集する必要があります。

3. Handler.phpでJSONエラーレスポンスを返す基本的な書き方

3. Handler.phpでJSONエラーレスポンスを返す基本的な書き方
3. Handler.phpでJSONエラーレスポンスを返す基本的な書き方

それでは実際にapp/Exceptions/Handler.phpを使って、APIにエラーが起きたときにJSON形式でレスポンスを返す方法を見ていきましょう。

register()メソッドの中にrenderable()を使って処理を書いていきます。以下は、データが見つからなかったときに発生するModelNotFoundExceptionをJSONで返す例です。


<?php

namespace App\Exceptions;

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class Handler extends ExceptionHandler
{
    public function register(): void
    {
        $this->renderable(function (ModelNotFoundException $e, $request) {
            // リクエストがAPIからかどうかを確認する
            if ($request->expectsJson()) {
                return response()->json([
                    'status'  => 'error',
                    'message' => 'データが見つかりませんでした。',
                ], 404);
            }
        });
    }
}

$request->expectsJson()は、アクセスしてきた相手がJSONを期待しているかどうかを調べるメソッドです。これがtrueのときだけJSONで返すようにすることで、通常のWebページのアクセスには影響を与えずにAPIだけに対応した処理を書けます。

このコードを実行してAPIにアクセスすると、以下のようなJSONが返ってきます。


{
    "status": "error",
    "message": "データが見つかりませんでした。"
}

4. バリデーションエラーをJSONで返す方法

4. バリデーションエラーをJSONで返す方法
4. バリデーションエラーをJSONで返す方法

APIでよく扱うエラーのひとつがバリデーションエラーです。バリデーションとは「入力チェック」のことで、たとえばメールアドレスの形式が正しくない、必須項目が空欄のままになっているなど、受け取ったデータが正しい形かどうかを確認する処理です。

Laravelのバリデーションが失敗するとValidationExceptionという例外が発生します。通常のWebページではフォームの画面にエラーメッセージが表示されますが、APIの場合はJSONで返す必要があります。

以下のようにHandler.phpに記述することで、バリデーションエラーの内容をJSON形式にして返すことができます。


<?php

use Illuminate\Validation\ValidationException;

public function register(): void
{
    $this->renderable(function (ValidationException $e, $request) {
        if ($request->expectsJson()) {
            return response()->json([
                'status'  => 'error',
                'message' => '入力内容に誤りがあります。',
                'errors'  => $e->errors(), // 各項目のエラー内容
            ], 422);
        }
    });
}

$e->errors()はバリデーションで失敗した項目と理由を配列として返すメソッドです。ステータスコードの422は「入力内容が処理できない形式だった」ことを示す番号です。このようにすることで、どの項目でどんなエラーが起きたかをAPIの利用者に正確に伝えることができます。

5. 認証エラーをJSONで返す方法

5. 認証エラーをJSONで返す方法
5. 認証エラーをJSONで返す方法

APIを使ったシステムでは、ログインしていない状態でアクセスしてきたユーザーに対して「認証が必要です」というエラーを返す場面が多くあります。Laravelでは認証が必要なページに未認証のままアクセスするとAuthenticationExceptionが発生します。

認証とは、「あなたは本当に誰ですか?」を確認することです。ウェブサービスでいえばログイン状態のチェックにあたります。

以下のようにHandler.phpへ書くことで、未認証のAPIアクセスに対してJSONエラーを返せます。


<?php

use Illuminate\Auth\AuthenticationException;

public function register(): void
{
    $this->renderable(function (AuthenticationException $e, $request) {
        if ($request->expectsJson()) {
            return response()->json([
                'status'  => 'error',
                'message' => '認証が必要です。ログインしてください。',
            ], 401);
        }
    });
}

ステータスコード401は「認証が必要」を意味します。APIの利用者はこのコードを受け取ることで「ログインしていないのでアクセスできなかった」と判断できます。このようにステータスコードとメッセージをセットで返すことが、わかりやすいAPIエラーレスポンスを設計するうえで大切なポイントです。

6. すべての例外をJSONで一括対応する方法

6. すべての例外をJSONで一括対応する方法
6. すべての例外をJSONで一括対応する方法

個別の例外ごとに処理を書く方法もありますが、想定外の例外が起きたときにも必ずJSON形式で返したいという場合は、すべての例外をまとめて処理する方法が便利です。

LaravelではThrowableという型を使うと、どんな種類の例外でもキャッチすることができます。Throwableとは、PHPにおいてすべての例外やエラーの親にあたる型のことです。


<?php

use Throwable;

public function register(): void
{
    $this->renderable(function (Throwable $e, $request) {
        if ($request->expectsJson()) {
            // HTTPステータスコードを取得する(取得できない場合は500)
            $status = method_exists($e, 'getStatusCode')
                ? $e->getStatusCode()
                : 500;

            return response()->json([
                'status'  => 'error',
                'message' => $e->getMessage() ?: 'サーバーエラーが発生しました。',
            ], $status);
        }
    });
}

method_exists()は、そのオブジェクトに指定したメソッドが存在するかどうかを調べる関数です。getStatusCode()メソッドが存在する例外ならそのコードを使い、存在しない場合は500(サーバー内部エラー)をセットしています。このようにしておくと、どんな予期せぬエラーが起きてもJSONで統一されたレスポンスを返せるので安心です。

7. JSONエラーレスポンスの設計で意識すること

7. JSONエラーレスポンスの設計で意識すること
7. JSONエラーレスポンスの設計で意識すること

APIのエラーレスポンスを設計するときは、返すデータの形を統一しておくことがとても重要です。形がバラバラだと、APIを利用する側(スマホアプリや他のシステム)が受け取ったデータを処理するのが難しくなります。

よく使われるJSONエラーレスポンスの形式としては、status(成功か失敗か)、message(人間向けのメッセージ)、errors(詳細なエラー情報)、code(エラーの種類を示す独自コード)などをセットにするパターンがあります。

また、HTTPステータスコードも適切なものを選ぶことが大切です。よく使うものをまとめると次のとおりです。400番台はクライアント(アクセスしてきた側)のミス、500番台はサーバー側の問題を示します。400は「リクエストの形式が正しくない」、401は「認証が必要」、403は「アクセス権限がない」、404は「リソースが見つからない」、422は「バリデーションエラー」、500は「サーバー内部エラー」をそれぞれ意味します。

このようにエラーの種類とステータスコードを正しく対応させることで、APIの利用者がエラーの原因を素早く把握できる、使いやすいAPIが完成します。LaravelのHandler.phpを活用することでこれらの設定をひとつのファイルにまとめて管理できるため、メンテナンスもしやすくなります。

カテゴリの一覧へ
新着記事
New1
Symfony
Symfonyとは?PHPの堅牢なフレームワークの特徴と活用シーン
New2
Laravel
Laravelのルーティングの基本構文と書き方をやさしく解説!初心者でも理解できるWebルートの仕組み
New3
Laravel
LaravelでAPI用のJSONエラーレスポンスを整形する方法!初心者向け完全ガイド
New4
CodeIgniter
CodeIgniterでカスタム例外クラスを作成する方法!初心者向けエラーハンドリング徹底解説
人気記事
No.1
Java&Spring記事人気No1
Laravel
Laravelでモデルを作成する方法をやさしく解説!php artisan make:model入門
No.2
Java&Spring記事人気No2
Laravel
Laravelでルーティングを設定する方法!web.phpと基本ルートの書き方を初心者向けに徹底解説
No.3
Java&Spring記事人気No3
Laravel
Laravelでセッションを扱う方法!保存方法と利用例を解説
No.4
Java&Spring記事人気No4
Laravel
Laravelで特定のSeederだけ実行する方法!db:seed --class=で必要なデータだけ登録
No.5
Java&Spring記事人気No5
Laravel
Laravelの認証ミドルウェアauthとguestを徹底解説!初心者でもわかるルート制御ガイド
No.6
Java&Spring記事人気No6
Laravel
Laravelでモデルからデータを取得・保存・更新・削除する方法を完全ガイド!初心者でもわかるEloquent ORM入門
No.7
Java&Spring記事人気No7
Laravel
Laravelのuniqueバリデーションを使ったユニーク制約の設定方法
No.8
Java&Spring記事人気No8
Symfony
Symfonyでフォームデータを受け取り処理する方法を完全解説!初心者でも理解できる入門ガイド