【PHP】LaravelでRESTful APIを作成する方法

対象バージョン: Laravel 13.x / PHP 8.3+(2026年時点のシリーズ基準)
一次ソース: Routing / Controllers / Responses / Eloquent Resources / Validation

こんにちは。この記事では、Laravel 13.x で RESTful API を作成する基本手順を、現行の公式ドキュメントに沿って整理します。install:api による API ルーティングの有効化から、apiResource による CRUD、バリデーションと JSON レスポンス、Eloquent Resource の最小例までを通します。Passport・GraphQL・Sanctum の深掘りは扱いません。まずは「動く JSON API を自分で組める」状態を目指します。

この記事で分かること

  • Laravel 13.x で API ルート(routes/api.php)を有効にする手順
  • Route::apiResource と make:controller --api による CRUD
  • バリデーション失敗時の 422 JSON
  • response()->json と Eloquent Resource の最小利用
  • API 認証の概要(auth:sanctum の高レベル言及)

対象バージョン

本記事の前提は Laravel 13.x / PHP 8.3+ です。Laravel 13 は 2026年3月17日リリースの現行メジャーであり、サポート表上 PHP 8.3〜8.5 を対象とします(Release Notes)。フレームワーク本体も php: ^8.3 を要求します。

古い記事にあった文字列コントローラルート(例: PostController@index)は、現行 Laravel の既定では自動名前空間解決されず、学習用の主例として不適切です。以降は配列構文または apiResource のみを使います。


APIルーティングの準備

fresh な 13.x には routes/api.php がありません

laravel/laravel 13.x の fresh スケルトンの routes/ には、既定で web.php と console.php のみがあります。routes/api.php は最初から存在しません。また bootstrap/app.php も、既定では withRouting に api: 引数がありません。

php artisan install:api で有効化する

ステートレスな API を提供する場合は、次のコマンドで API ルーティングを有効化します(Routing — API Routes)。

php artisan install:api

このコマンドは Laravel Sanctum をインストールし、routes/api.php を作成します。以降のルート例は、この手順を済ませた前提です。

/api 接頭辞と api ミドルウェアグループ

routes/api.php に書いたルートには、自動で /api URI 接頭辞 が付きます。たとえば Route::get('/posts', ...) の実 URL は /api/posts です。あわせて、これらのルートは ステートレス で、api ミドルウェアグループ に割り当てられます。

install:api が生成する例には auth:sanctum が付いていることがあります。公開してよいルートでは auth:sanctum を省略して構いません。保護したいルートにだけ付けます。


APIルーティング

CRUD の REST エンドポイントは、個別に5本書くより Route::apiResource を使うのが公式の推奨です。create / edit(HTML 用)ルートは含まれません。

<?php

use App\Http\Controllers\Api\PostController;
use Illuminate\Support\Facades\Route;

Route::apiResource('posts', PostController::class);

登録されるアクションと HTTP 動詞の対応は次のとおりです(実 URL はすべて /api 接頭辞付き)。

メソッド URI アクション
GET /api/posts index
POST /api/posts store
GET /api/posts/{post} show
PUT/PATCH /api/posts/{post} update
DELETE /api/posts/{post} destroy

個別に定義する場合は、配列構文のみを使います。

Route::get('/posts', [PostController::class, 'index']);
Route::post('/posts', [PostController::class, 'store']);
Route::get('/posts/{post}', [PostController::class, 'show']);
Route::put('/posts/{post}', [PostController::class, 'update']);
Route::delete('/posts/{post}', [PostController::class, 'destroy']);

使わない構文: 'PostController@index' のような文字列コントローラルートは、現行の主例にしません。


APIコントローラ

API 用のリソースコントローラは、--api オプション付きで生成します。

php artisan make:controller Api/PostController --api

create / edit を含まず、index / store / show / update / destroy が用意されます。サブディレクトリ(例: Api/)も問題ありません。

show / update / destroy では、暗黙のルートモデルバインディングを使うと簡潔です。ルートパラメータ {post} と型ヒント Post $post が一致すればモデルが注入され、見つからない場合は 404 になります。

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function show(Post $post)
    {
        return $post;
    }
}

(モデルを直接返すと、hidden 属性を尊重しつつ自動で JSON になります。実務では後述の Resource か response()->json に寄せると見通しが良くなります。)


バリデーションとエラーJSON

入力検証は、Web と同様に $request->validate([...]) または Form Request の型ヒントで行えます。

public function store(Request $request)
{
    $validated = $request->validate([
        'title' => ['required', 'string', 'max:255'],
        'body' => ['required', 'string'],
    ]);

    $post = Post::create($validated);

    return response()->json($post, 201);
}

XHR / JSON を期待するリクエストでバリデーションに失敗すると、リダイレクトではなく 422 Unprocessable Entity と、message / errors 形式の JSON が返ります(Validation)。API クライアント側はこのステータスを前提にエラー表示を組み立てるとよいです。


レスポンスのフォーマット

response()->json

response()->json($data, $status) で Content-Type: application/json のレスポンスを返せます。第2引数で HTTP ステータスを指定します(既定は 200。作成時は 201 など)。

return response()->json(['message' => 'Post created successfully'], 201);

よく使うステータスの目安です。

コード 用途の例
200 取得・更新の成功
201 作成の成功
404 リソース未検出(ルートモデルバインディング含む)
422 バリデーション失敗

Eloquent API Resource(最小)

変換層として Eloquent API Resource を使うと、公開する属性を明示できます。

php artisan make:resource PostResource
<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class PostResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'body' => $this->body,
            'created_at' => $this->created_at,
        ];
    }
}

コントローラからは次のように返します。

use App\Http\Resources\PostResource;

return new PostResource($post);
// 一覧
return PostResource::collection(Post::all());

入門では単一 Resource と ::collection までで十分です。


API認証(概要)

install:api により Laravel Sanctum が入ります。保護したいルートには auth:sanctum ミドルウェアを付けます。

Route::middleware('auth:sanctum')->group(function () {
    Route::apiResource('posts', PostController::class);
});

公開ルートではこの middleware を付けなくて構いません。トークン発行の詳細、SPA Cookie 認証、Passport、カスタムガードなどは本記事の範囲外です。API トークン認証が必要になったら、公式の Sanctum を参照してください。


最小CRUDの流れ

ここまでの手順を、動作イメージとして並べます。

  1. php artisan install:api — routes/api.php と Sanctum を用意
  2. モデル/マイグレーション — 例: Post(Eloquent 前提は既存知識で可)
  3. php artisan make:controller Api/PostController --api
  4. (任意)php artisan make:resource PostResource
  5. routes/api.php に Route::apiResource('posts', PostController::class);
  6. 各アクションで validate → 永続化 → PostResource または response()->json(..., 201)

コントローラの最小実装例です。

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use App\Models\Post;
use Illuminate\Http\Request;

class PostController extends Controller
{
    public function index()
    {
        return PostResource::collection(Post::all());
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
        ]);

        $post = Post::create($validated);

        return response()->json($post, 201);
    }

    public function show(Post $post)
    {
        return new PostResource($post);
    }

    public function update(Request $request, Post $post)
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
        ]);

        $post->update($validated);

        return new PostResource($post);
    }

    public function destroy(Post $post)
    {
        $post->delete();

        return response()->json(['message' => 'Post deleted successfully']);
    }
}

補足: 作成成功は 201、取得・更新・削除成功は既定の 200 を使う例です。ステータスはプロジェクトの方針に合わせて調整してください。

動作確認の例(ローカル):

# 一覧
curl -s http://127.0.0.1:8000/api/posts

# 作成
curl -s -X POST http://127.0.0.1:8000/api/posts \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{"title":"Hello","body":"API"}'

Accept: application/json を付けると、バリデーション失敗時に 422 JSON を受け取りやすくなります。


最後に

Laravel 13.x で RESTful API を作る流れは、次のようにまとめられます。

  1. php artisan install:api で routes/api.php(/api 接頭辞)を有効化
  2. make:controller ... --api と Route::apiResource で CRUD を登録
  3. validate と 422 JSON、response()->json / Eloquent Resource で応答を整える
  4. 必要なルートだけ auth:sanctum で保護

タイトルどおり「RESTful API を作成する」入口として、まずはこの最小 CRUD を動かしてみてください。認証の詳細や高度な API 設計は、公式ドキュメントへ進むとよいです。

参考リンク

コメントする