Laravel API開発の基礎から応用まで:効率的なバックエンド構築ガイド

Laravel入門

Laravel APIとは、LaravelでJSON形式のレスポンスを返すRESTful APIを構築する仕組み全般を指します。LaravelはPHPによるWebアプリケーション開発のための優れたフレームワークであり、シンプルかつ強力なAPI開発機能を備えています。この記事ではLaravel 12を前提に、APIを作成する最小手順から認証・バリデーション・エラーハンドリング、外部APIとの連携までを体系的に解説します。

LaravelでAPIを作成する最小手順

Laravelで最小構成のAPIを動かすために必要な手順は5ステップです。

  1. プロジェクト作成composer create-project laravel/laravel api-project
  2. API有効化php artisan install:api(Laravel 12以降は必須)
  3. モデル・マイグレーション作成php artisan make:model Post -mcr
  4. ルート定義routes/api.phpRoute::apiResourceを追加
  5. 動作確認php artisan serveでローカルサーバーを起動しGET /api/postsを叩く

以降のセクションで各ステップを詳しく説明します。

Laravelのセットアップ(Laravel 12)

API開発を始める前に、ComposerとPHP 8.2以上がインストールされていることを確認してください。

新規プロジェクトの作成

composer create-project laravel/laravel api-project
cd api-project

APIルーティングの有効化(Laravel 12の変更点)

Laravel 12ではroutes/api.phpbootstrap/app.phpへのAPI設定がデフォルトで含まれていません。以下のコマンドで追加します。

php artisan install:api

このコマンドを実行すると次の変更が行われます:

  • routes/api.phpが生成される
  • bootstrap/app.phpにAPIルートが登録される
  • Laravel Sanctumがインストールされ、personal_access_tokensテーブルのマイグレーションが追加される

install:apiコマンドのオプションや内部動作の詳細はinstall:api — APIをインストールするコマンドで解説しています。

APIルーティング

routes/api.phpにルートを定義します。Laravel 12では文字列ベースのコントローラー指定は非推奨のため、配列構文を使用します。

リソースルート(推奨)

use App\Http\Controllers\PostController;

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

apiResourceは以下のルートを一括生成します:

メソッド URI アクション 説明
GET /api/posts index 一覧取得
POST /api/posts store 作成
GET /api/posts/{post} show 1件取得
PUT/PATCH /api/posts/{post} update 更新
DELETE /api/posts/{post} destroy 削除

個別ルートの定義

use App\Http\Controllers\PostController;

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']);

ルートのグループ化やミドルウェア設定、バージョニングなどルーティングをより深く理解したい場合は、Laravel API Route設定方法:RESTful API構築の基本とベストプラクティスも参考にしてください。

Controller / FormRequest / Resource / Eloquentの役割

LaravelのAPI開発では、責務を分離した4つのコンポーネントを組み合わせて使います。

コンポーネント 役割 生成コマンド
Controller HTTPリクエストを受け取り、処理を振り分ける make:controller PostController --api
FormRequest バリデーションルールの定義・認可ロジック make:request StorePostRequest
Resource EloquentモデルをJSONレスポンス用に変換する make:resource PostResource
Eloquent Model DBとのデータのやり取り(ORM) make:model Post -m

最小のCRUD API実装例

Postリソースを題材に、最小構成のCRUD APIを実装します。

モデルとマイグレーション

php artisan make:model Post -mcr
# -m: マイグレーション生成
# -c: コントローラー生成
# -r: リソースコントローラー(index/store/show/update/destroy)

database/migrations/xxxx_create_posts_table.phpを編集します:

Schema::create('posts', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->timestamps();
});
php artisan migrate

Eloquentモデル

// app/Models/Post.php
class Post extends Model
{
    protected $fillable = ['title', 'body'];
}

FormRequest(バリデーション)

php artisan make:request StorePostRequest
php artisan make:request UpdatePostRequest
// app/Http/Requests/StorePostRequest.php
class StorePostRequest extends FormRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'title' => ['required', 'string', 'max:255'],
            'body'  => ['required', 'string'],
        ];
    }
}

APIリソース

php artisan make:resource PostResource
// app/Http/Resources/PostResource.php
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->toISOString(),
        ];
    }
}

コントローラー

// app/Http/Controllers/PostController.php
use App\Http\Requests\StorePostRequest;
use App\Http\Requests\UpdatePostRequest;
use App\Http\Resources\PostResource;
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        return PostResource::collection(Post::latest()->paginate(15));
    }

    public function store(StorePostRequest $request)
    {
        $post = Post::create($request->validated());
        return new PostResource($post);
    }

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

    public function update(UpdatePostRequest $request, Post $post)
    {
        $post->update($request->validated());
        return new PostResource($post);
    }

    public function destroy(Post $post)
    {
        $post->delete();
        return response()->noContent(); // 204
    }
}

バリデーションとエラーレスポンス

FormRequestを使うとバリデーション失敗時に自動で422 Unprocessable Entityが返ります。

バリデーション失敗時のレスポンス例

{
  "message": "The title field is required.",
  "errors": {
    "title": ["The title field is required."],
    "body":  ["The body field is required."]
  }
}

カスタムエラーメッセージ

public function messages(): array
{
    return [
        'title.required' => 'タイトルは必須です。',
        'body.required'  => '本文は必須です。',
    ];
}

モデルが見つからない場合(404)

ルートモデルバインディングを使えば、存在しないIDへのアクセスは自動的に404を返します。追加コード不要です。

// {post} がDBに存在しない場合、自動で404を返す
Route::get('/posts/{post}', [PostController::class, 'show']);

手動での例外スロー

use Illuminate\Http\Exceptions\HttpResponseException;

if (!$condition) {
    throw new HttpResponseException(response()->json([
        'message' => 'アクセス権限がありません。',
    ], 403));
}

認証の選択肢

LaravelでAPIに認証を加える場合、主に3つの方法があります。

方式 用途 特徴
Sanctum(SPAトークン) モバイルアプリ・外部クライアント向けAPI Bearerトークンで認証。シンプルで軽量
Sanctum(セッション認証) 同一オリジンのSPA(Nuxt/Next等) Cookieベース。CSRFトークンが必要
Passport OAuth2が必要な場合 フル機能のOAuth2サーバー。複雑さが増す

Sanctumでのトークン認証(推奨)

php artisan install:api実行済みであればSanctumは導入済みです。

// routes/api.php

// ログイン(トークン発行)
Route::post('/login', function (Request $request) {
    $request->validate([
        'email'    => 'required|email',
        'password' => 'required',
    ]);

    $user = User::where('email', $request->email)->first();

    if (!$user || !Hash::check($request->password, $user->password)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    $token = $user->createToken('api-token')->plainTextToken;

    return response()->json(['token' => $token]);
});

// 認証が必要なルートグループ
Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', fn(Request $request) => $request->user());
    Route::apiResource('posts', PostController::class);
});

クライアントはリクエストヘッダーにトークンを付与して送信します:

curl -H "Authorization: Bearer {token}" https://example.com/api/posts

セッション認証とトークン認証の違い

項目 セッション認証 トークン認証(Sanctum)
状態の保持 サーバー側(セッションストア) クライアント側(トークン)
用途 ブラウザベースのSPA モバイルアプリ・外部API連携
CSRF対策 必要 不要(Bearerトークンを使用)
スケーラビリティ セッションサーバー依存 ステートレスで水平スケール容易

Sanctum認証の詳細な設定手順はLaravel Sanctumを使ってREST API認証をシンプルに実装する方法、OAuth2が必要な場合の実装はLaravel Passportを使ったAPI認証入門:設定から実装まで徹底解説で詳しく解説しています。

エラーハンドリング

API開発では、エラーレスポンスを一貫したJSON形式で返すことが重要です。Laravel 12ではデフォルトでJSON形式のエラーレスポンスが返りますが、bootstrap/app.phpでカスタマイズできます。

// bootstrap/app.php
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (Throwable $e, Request $request) {
        if ($request->expectsJson()) {
            $status = method_exists($e, 'getStatusCode')
                ? $e->getStatusCode()
                : 500;

            return response()->json([
                'message' => $e->getMessage(),
            ], $status);
        }
    });
})

テスト駆動開発(TDD)の実践

安定したAPIを提供するためにはテストが欠かせません。LaravelはPHPUnitPestをサポートしています。

php artisan make:test PostApiTest
public function test_can_create_post(): void
{
    $response = $this->postJson('/api/posts', [
        'title' => 'テスト投稿',
        'body'  => '本文テキスト',
    ]);

    $response->assertStatus(201);
    $this->assertDatabaseHas('posts', ['title' => 'テスト投稿']);
}

public function test_validation_fails_without_title(): void
{
    $response = $this->postJson('/api/posts', ['body' => '本文のみ']);

    $response->assertStatus(422)
             ->assertJsonValidationErrors(['title']);
}

応用:外部APIとの連携・ドキュメント生成

ここまでは自作APIを提供する側の実装でしたが、Laravel APIの応用として次の2つもよく使われます。

外部APIを呼び出す(Guzzle)

決済サービスや地図APIなど外部のAPIをLaravelアプリから呼び出す場合は、標準搭載のHTTPクライアント(Guzzleラッパー)を使います。

use Illuminate\Support\Facades\Http;

$response = Http::withToken($apiToken)
    ->get('https://api.example.com/items');

$items = $response->json();

リトライやタイムアウト、認証ヘッダーの付与など実践的な使い方はLaravelとGuzzleを使ったAPIリクエストの効率的な実装ガイドで解説しています。

APIドキュメントを自動生成する

作成したAPIの仕様書をチームや外部連携先と共有する場合は、OpenAPI(Swagger)形式でドキュメントを自動生成できます。生成方法の詳細はLaravel OpenAPIを活用して効率的にAPIドキュメントを生成する方法を参照してください。

デプロイ

開発完了後は本番環境へデプロイします。Laravelは多くのクラウドホスティングサービスと互換性があり、Laravel ForgeやVaporが広く使われています。これらのサービスは自動デプロイメントやスケーリング機能を備えており、APIを迅速に展開するのに役立ちます。

FAQ

LaravelでAPIを作るには?

以下の手順で最小構成のAPIを作れます:

  1. composer create-project laravel/laravel api-projectでプロジェクト作成
  2. php artisan install:apiでAPIルートとSanctumを有効化
  3. モデル・コントローラー・リソースを作成してroutes/api.phpにルートを定義
  4. php artisan serveで起動し動作確認

APIルートはどこに書く?

routes/api.phpに記述します。このファイルのルートには自動的に/apiプレフィックスが付きます(例:Route::get('/posts')/api/posts)。Laravel 12ではphp artisan install:apiを実行しないとroutes/api.phpが生成されない点に注意してください。

認証はどうする?

モバイルアプリや外部クライアント向けAPIにはLaravel Sanctumのトークン認証が最もシンプルで推奨です。同一オリジンのSPAならSanctumのセッション認証、OAuth2が必要な場合はPassportを選択します。php artisan install:api実行でSanctumが自動インストールされます。

外部APIとの連携はどうする?

Laravelから他社サービスのAPIを呼び出す場合は、標準搭載のHttpファサード(Guzzleラッパー)を使います。決済・地図・SNS連携などLaravelアプリ側がクライアントになるケースでは、この方法が基本です。

まとめ

この記事では、Laravel 12を前提にAPIを構築するための手順を説明しました。

  • Laravel 12ではphp artisan install:apiでAPIルートとSanctumを有効化する
  • Controller / FormRequest / Resource / Eloquentの役割を分離することで保守性が高まる
  • FormRequestを使えばバリデーションとエラーレスポンスが自動化される
  • Sanctumのトークン認証が外部API向けの標準的な選択肢
  • 外部APIを呼び出す側になる場合はHttpファサード(Guzzle)を使う

これらの要素を適切に組み合わせることで、堅牢で拡張性の高いAPIを迅速に構築できます。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント