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 を開発する

ユーザからコメント一覧を取得するリレーションシップ

ここではあるユーザが投稿したコメントを一覧で取得するリレーションシップを作成します.具体的には User モデルを編集して,comments() 関数を次のように作成します.

app/Models/User.php
<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    // One to Many の One 側
    public function comments()
    {
        return $this->hasMany('App\Models\Comment');
    }
}

ルートの定義を編集して /user という URI のルートを追加します.この時,auth:sanctum のミドルウェアの中に追加していることに注意してください.これにより,/user にアクセスするには認証トークンの付与が必須になります.

routes/api.php (抜粋)
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::get('/user', [UserController::class, 'show']) -> name('user.show');
});

コントローラを編集して,show()関数を追加します.とりあえずは認証されたユーザ情報を返すだけの内容にしておきます.

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

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
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);
    }

    function show()
    {
        $user = Auth::user();
        return $user;
    }
}

今の状態で curl コマンドで接続するとユーザの情報が表示されました.ここで,ユーザのパスワード情報は表示されていないことに注意してください.これはモデルファイル(31-32行目)において protected $hidden'password" が設定されているからです.

C:\Users\Rinsaka>curl -H "Authorization: Bearer 1|fzYV0EEfaDBGy5sifY9V3A6LWZBPmZklpWy4Auxd018912e0" http://192.168.56.101:8000/api/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"}
C:\Users\Rinsaka>curl -H "Authorization: Bearer 2|mAcqEZVmlUYs9qM4LuuKyWwCihEhfsW0f65M5Bexbcd36bb8" http://192.168.56.101:8000/api/user/ ⏎
{"id":2,"name":"B. Sample","email":"b@sample.com","email_verified_at":null,"created_at":"2023-11-02T15:02:01.000000Z","updated_at":"2023-11-02T15:02:01.000000Z"}
C:\Users\Rinsaka>

ユーザが投稿したコメントを一覧で取得するにはコントローラーの show() 関数を次の様に変更します.

app/Http/Controllers/UserController.php (抜粋)
    function show()
    {
        $user = Auth::user();
        return $user->comments;
    }

再び curl コマンドで接続すると,認証されたユーザが所有者になっているコメントだけが一覧で取得できるようになりました.

C:\Users\Rinsaka>curl -H "Authorization: Bearer 1|fzYV0EEfaDBGy5sifY9V3A6LWZBPmZklpWy4Auxd018912e0" http://192.168.56.101:8000/api/user/ ⏎
[{"id":1,"title":"\u6700\u521d\u306e\u30b3\u30e1\u30f3\u30c8","body":"\u6700\u521d\u306e\u30b3\u30e1\u30f3\u30c8\u3067\u3059\uff01","user_id":1,"created_at":"2023-10-02T01:10:10.000000Z","updated_at":"2023-10-02T01:10:10.000000Z"},{"id":3,"title":"<\u4e09\u500b\u76ee>\u306e\u30b3\u30e1\u30f3\u30c8","body":"\u30b7\u30fc\u30c0\u306b\u3088\u3063\u3066\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u8a2d\u5b9a\u3057\u307e\u3059\uff0e","user_id":1,"created_at":"2023-10-02T01:30:10.000000Z","updated_at":"2023-10-02T01:30:10.000000Z"},{"id":4,"title":"\u4f50\u3005\u6728 \u76f4\u6a39","body":"4809489  \u5175\u5eab\u770c\u6d25\u7530\u5e02\u6771\u533a\u5409\u7530\u753a\u5b87\u91ce4-7-7 \u30cf\u30a4\u30c4\u5742\u672c105\u53f7 \/ xyoshimoto@example.com","user_id":1,"created_at":"2023-10-29T15:00:00.000000Z","updated_at":"2023-11-25T03:29:44.000000Z"},

...(以下略)...

さらに,ユーザ情報とコメントの両方を表示するにはコントローラをコントローラを次のように変更します.

app/Http/Controllers/UserController.php (抜粋)
    function show()
    {
        $user = Auth::user();
        return ['user' => $user, 'comments' => $user->comments];
    }

今度はユーザ情報とコメントの一覧が取得できました.

C:\Users\Rinsaka>curl -H "Authorization: Bearer 1|fzYV0EEfaDBGy5sifY9V3A6LWZBPmZklpWy4Auxd018912e0" http://192.168.56.101:8000/api/user/ ⏎
{"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","comments":[{"id":1,"title":"\u6700\u521d\u306e\u30b3\u30e1\u30f3\u30c8","body":"\u6700\u521d\u306e\u30b3\u30e1\u30f3\u30c8\u3067\u3059\uff01","user_id":1,"created_at":"2023-10-02T01:10:10.000000Z","updated_at":"2023-10-02T01:10:10.000000Z"},{"id":3,"title":"<\u4e09\u500b\u76ee>\u306e\u30b3\u30e1\u30f3\u30c8","body":"\u30b7\u30fc\u30c0\u306b\u3088\u3063\u3066\u30c6\u30b9\u30c8\u30c7\u30fc\u30bf\u3092\u8a2d\u5b9a\u3057\u307e\u3059\uff0e","user_id":1,"created_at":"2023-10-02T01:30:10.000000Z","updated_at":"2023-10-02T01:30:10.000000Z"},{"id":4,"title":"\u4f50\u3005\u6728 \u76f4\u6a39","body":"4809489  \u5175\u5eab\u770c\u6d25\u7530\u5e02\u6771\u533a\u5409\u7530\u753a\u5b87\u91ce4-7-7 \u30cf\u30a4\u30c4\u5742\u672c105\u53f7 \/ xyoshimoto@example.com","user_id":1,"created_at":"2023-10-29T15:00:00.000000Z","updated_at":"2023-11-25T03:29:44.000000Z"},

...(以下略)...

上の結果ではコメントの件名や本文が Unicode エンコーディングされています.ここと同じようにリソースを活用して人間が読める形式に変換しても良いでしょう.

目次に戻る