Laravel 10 入門トップページ


目次

  1. API とプロジェクトの概要
  2. プロジェクトの作成と初期設定
  3. データベースのマイグレーション
  4. シーダによるコメントデータの登録
  5. モデルの生成
  6. リソースの生成
  7. GETメソッドを利用した個別コメント取得のAPI作成
  8. 日本語文字列の表示と日時の調整
  9. GETメソッドを利用したコメント一覧取得のAPI作成
  10. データのラップ
  11. POSTメソッドを利用したコメントの新規投稿APIの作成
  12. PUTメソッドを利用したコメント更新APIの作成
  13. DELETEメソッドを利用したコメント削除APIの作成
  14. シーダの拡張
  15. ページネーションの実装
  16. 個別コメントをコントローラで取得
  17. Postman の利用
  18. ユーザ情報を登録する
  19. Sanctum によるユーザ認証
  20. ログインとトークン
  21. コメントとユーザのリレーションシップ
  22. 新規投稿時にユーザIDを記録する
  23. コメントからユーザ名を表示するリレーションシップ
  24. ユーザからコメント一覧を取得するリレーションシップ
  25. 更新と削除の権限設定
  26. 発行済みトークンの取得
  27. トークンの有効期限
  28. レート制限
  29. 閲覧権限の緩和

Laravel で API を開発する

Sanctum によるユーザ認証

Laravel API でのユーザの認証は Sanctum パッケージを利用すると効率的に実装ができます.Sanctum パッケージはプロジェクトの新規作成と同時にインストールされているはずです.Sanctum パッケージがインストールされていない場合や,Sandtum に必要なファイルを削除してしまっている場合などは次のコマンドで Sanctum をインストールします.

vagrant@ubuntu2204 CommentAPI $ php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" ⏎

   INFO  Publishing assets.

  Copying directory [vendor/laravel/sanctum/database/migrations] to [database/migrations]  DONE
  File [config/sanctum.php] already exists ..................... SKIPPED

vagrant@ubuntu2204 CommentAPI $

次に,Kernel.php を修正して Sanctum を有効化します.具体的には 'api' の設定項目で Sanctum の設定がコメントになっているので,このコメントを解除します.

app/Http/Kernel.php
'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    \Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

現在のルート定義を確認するとコメントの機能に関する幾つかのルートが次のとおり存在しています.

routes/api.php (抜粋)
Route::get('/comments', [CommentController::class, 'index']) -> name('comments.index');
Route::get('/comments/{comment_id}', [CommentController::class, 'show']) -> name('comments.show');
Route::post('/comments', [CommentController::class, 'store']) -> name('comments.store');
Route::put('/comments/{comment_id}', [CommentController::class, 'update']) -> name('comments.update');
Route::delete('/comments/{comment_id}', [CommentController::class, 'destroy']) -> name('comments.destroy');

これらの全ての機能を利用するときに認証を必要としたいので,auth:sanctummiddleware で囲います.さらに,ログインのルートも定義します.なお,「ログイン」という名称を使っていますが,「トークンの発行」という意味合いで利用するので,名前は変更した方が直感的かもしれません.

routes/api.php
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

use App\Http\Controllers\CommentController;
use App\Http\Controllers\UserController;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider and all of them will
| be assigned to the "api" middleware group. Make something great!
|
*/

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Route::group(['middleware' => 'auth:sanctum'], function(){
    Route::get('/comments', [CommentController::class, 'index']) -> name('comments.index');
    Route::get('/comments/{comment_id}', [CommentController::class, 'show']) -> name('comments.show');
    Route::post('/comments', [CommentController::class, 'store']) -> name('comments.store');
    Route::put('/comments/{comment_id}', [CommentController::class, 'update']) -> name('comments.update');
    Route::delete('/comments/{comment_id}', [CommentController::class, 'destroy']) -> name('comments.destroy');
});

Route::post('login', [UserController::class, 'login']);

次に UserController を作成します.

vagrant@ubuntu2204 CommentAPI $ php artisan make:controller UserController ⏎

   INFO  Controller [app/Http/Controllers/UserController.php] created successfully.

vagrant@ubuntu2204 CommentAPI $

app/Http/Controllers/UserController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\User;

class UserController extends Controller
{
    function login(Request $request)
    {
        $user = User::where('email', $request->email)->first();
        if (!$user || !password_verify($request->password, $user->password)) {
            return response([
                'message' => ['認証情報が異なります']
            ], 404);
        }

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

        $response = [
            'user' => $user,
            'token' => $token
        ];

        return response($response, 201);
    }
}

コマンドを使ってルートの定義を確認します.

vagrant@ubuntu2204 CommentAPI $ php artisan route:list

  GET|HEAD  / ..........................................................
  POST      _ignition/execute-solution ignition.executeSolution › Spati…
  GET|HEAD  _ignition/health-check ignition.healthCheck › Spatie\Larave…
  POST      _ignition/update-config ignition.updateConfig › Spatie\Lara…
  GET|HEAD  api/comments ...... comments.index › CommentController@index
  POST      api/comments ...... comments.store › CommentController@store
  GET|HEAD  api/comments/{comment_id} comments.show › CommentController…
  PUT       api/comments/{comment_id} comments.update › CommentControll…
  DELETE    api/comments/{comment_id} comments.destroy › CommentControl…
  POST      api/login ............................. UserController@login
  GET|HEAD  api/user ...................................................
  GET|HEAD  sanctum/csrf-cookie sanctum.csrf-cookie › Laravel\Sanctum  …

                                                     Showing [12] routes

vagrant@ubuntu2204 CommentAPI $

ルートの確認ができたので,curl コマンドを使って,(1) 認証情報を付与せずに閲覧,(2) 正しい認証情報を付与して閲覧,を順番に試みます.どちらの場合もエラーになりました.

C:\Users\Rinsaka>curl http://192.168.56.101:8000/api/comments/1/ ⏎
<!DOCTYPE html>
<html lang="en" class="auto">
<!--
Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined. in file /home/vagrant/Documents/laravel/CommentAPI/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 479

...(以下略)...

C:\Users\Rinsaka>curl -u a@sample.com:abc http://192.168.56.101:8000/api/comments/1/ ⏎
<!DOCTYPE html>
<html lang="en" class="auto">
<!--
Symfony\Component\Routing\Exception\RouteNotFoundException: Route [login] not defined. in file /home/vagrant/Documents/laravel/CommentAPI/vendor/laravel/framework/src/Illuminate/Routing/UrlGenerator.php on line 479

...(以下略)...

Web ブラウザで接続しても閲覧できません.

laravel10-2023-api-11.png

Postman で認証情報を付与しない場合も閲覧できません.

laravel10-2023-api-12.png

Laravel で Sanctum を使った場合はユーザ名とパスワードで API への接続を認証するわけではありません.実はユーザごとにトークンを発行して,そのトークンで認証を行います.まず,現時点ではデータベースの personal_access_token テーブルにデータが登録されていないことを確認します.

sqlite> .tables ⏎
comments                migrations              personal_access_tokens
failed_jobs             password_reset_tokens   users
sqlite> SELECT * FROM personal_access_tokens; ⏎
sqlite>

ログインのための URI (/api/login/) に POST メソッドでメールアドレスとパスワードの正しい組み合わせを送信するとトークンが発行されます.ここで表示されたトークンは確実にメモ(コピー)しておく必要があります.

C:\Users\Rinsaka>curl -X POST -d "email=a@sample.com" -d "password=abc" http://192.168.56.101:8000/api/login/ ⏎
{"user":{"id":1,"name":"A. Sample","email":"a@sample.com","email_verified_at":null,"created_at":"2023-11-02T15:01:01.000000Z","updated_at":"2023-11-02T15:01:01.000000Z"},"token":"1|LKP6Mb8mQQ7d0TJpRoxpsk8NoWFeDJvEPcNPu0gscf82b730"}
C:\Users\Rinsaka>

データベースで personal_acces_tokens テーブルを検索してトークンが発行されていることを確認します.ただし,データベースのテーブルにはトークンそのものが格納されているわけではなく,ハッシュ化されて保存されていることに注意してください.つまり,上で発行したトークンをハッシュ値から復元することはできません.

sqlite> SELECT * FROM personal_access_tokens; ⏎
id|tokenable_type|tokenable_id|name|token|abilities|last_used_at|expires_at|created_at|updated_at
1|App\Models\User|1|comments-api-token|0c94ec67889ac45b2963e7876260ce7452c8b3880963f5eb2a72aa1019e11324|["*"]|||2023-12-18 10:18:54|2023-12-18 10:18:54
sqlite>

トークンを取得できたので,そのトークンを利用してコメントの閲覧と投稿を行います.コマンド curl でトークンを付与するには -H オプションを利用して Bearer トークンとして次のように指定します.もちろんトークンは上の作業で発行されたものを指定してください.

C:\Users\Rinsaka>curl -H "Authorization: Bearer 1|LKP6Mb8mQQ7d0TJpRoxpsk8NoWFeDJvEPcNPu0gscf82b730" http://192.168.56.101:8000/api/comments/1/ ⏎
{"comment":{"id":1,"title":"最初のコメント","body":"最初のコメントです!","updated_at":"2023-10-02T10:10:10.000000Z"}}
C:\Users\Rinsaka>
C:\Users\Rinsaka>curl -X POST -d "title=auth sanctum" -d "body=token test" -H "Authorization: Bearer 1|LKP6Mb8mQQ7d0TJpRoxpsk8NoWFeDJvEPcNPu0gscf82b730" http://192.168.56.101:8000/api/comments/ ⏎
{"comment":{"id":101,"title":"auth sanctum","body":"token test","updated_at":"2023-12-18T10:30:01.000000Z"}}
C:\Users\Rinsaka>

次の様にすると Postman でも認証情報を付与することができます.まず,「認証」のページを開き,タイプで「Bearer トークン」を選びます.

laravel10-2023-api-13.png

次に,正しいトークンを入力(ペースト)します.

laravel10-2023-api-14.png

コメントの個別表示の URI を入力して「送信」ボタンを押下すると,1件のコメント情報を取得できました.

laravel10-2023-api-15.png

新規投稿の場合は「POST」メソッドを選択してトークンも設定します.

laravel10-2023-api-16.png

「パラメーター」のページを開いて「キー」と「値」を設定して「送信」ボタンを押下します.

laravel10-2023-api-17.png

新規投稿に成功すると画面下部のボックスに結果が表示されます.

laravel10-2023-api-18.png

コメントを一覧で取得すると今 Postman で投稿したコメントと直前に curl コマンドで投稿したコメントを確認できました.

laravel10-2023-api-19.png

これでトークンによる認証を必要とする API を実装することできました.PUT メソッドや DELETE メソッドも同じ方法でトークンを与えれば実行できることも確認してください.

目次に戻る