[Laravel] APIの作り方(ルーティング、コントローラ、CSRF保護)

スポンサーリンク

概要

LaravelでAPIを作成する場合、ルーティング、コントローラ(必要な場合はフォームリクエストも)を定義・作成する必要がある。

手順

1. コントローラの作成

  • sail artisan make:controller Api/ItemsController
  • 削除処理の場合はresponse()->noContent()を返す(204が返される)
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Item;
use Illuminate\Database\Eloquent\Collection;

class ItemsController extends Controller
{
    public function index(): Collection
    {
        return Item::orderBy('id', 'desc')->get();
    }

    public function store(Request $request): Item
    {
        $item = DB::transaction(function () use ($request) {
            $item = new Item();
            $item->name = $request->input('name');
            $item->save();
            return $item;
        });
        return $item;
    }

    public function update(Request $request, Item $item): Item
    {
        $item = DB::transaction(function () use ($request, $item) {
            $item->name = $request->input('name');
            $item->save();
            return $item;
        });
        return item;
    }

    public function destroy(Item $item): Response
    {
        DB::transaction(function () use ($item) {
            $item->delete();
        });
        return response()->noContent();
    }
}

2. ルートの定義

  • routes/api.phpにルートを追加する。
  • 定義したルートは/api/xxxでアクセスできるようになる。
    (ルートが/items/{team}の場合は/api/items/99のようになる)
  • APIはバックエンドから呼び出されることはないため、nameメソッドを使ってルートに名前を付ける必要はない。
    Route::get('/items', [ItemsController::class, 'index'])->name('item.index');のようには書かない)
<?php
use App\Http\Controllers\Api\ItemsController;
use Illuminate\Support\Facades\Route;

Route::put('/items/{team}', [ItemsController::class, 'update']);
Route::post('/items/{team}', [ItemsController::class, 'store']);
Route::delete('/items/{team}', [ItemsController::class, 'destroy']);
Route::get('/items', [ItemsController::class, 'index']);

3. ビュー

fetch("/api/items", {
  method: "GET",
  headers: { 
    "X-CSRF-TOKEN": {{csrf_token()}}, // CSRF保護されている場合は必要(後述)
    "Accept": "application/json",
    "Content-Type": "application/json",
  }
})
.then((response) => response.json())
.then(console.log);

CSRF保護

  • デフォルトではAPIルートはCSRFから保護されていないため、必要な場合はapp/Http/Kernel.phpのapiミドルウェアグループにミドルウェアを追加する。
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        \App\Http\Middleware\EncryptCookies::class, // 追加
        \Illuminate\Session\Middleware\StartSession::class,// 追加
        \App\Http\Middleware\VerifyCsrfToken::class, // 追加
        \Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],
];

参考サイト

おすすめ書籍

コメント