第7回 データのシリアライズとリソースの変換

Laravel WebAPI開発

こんにちは、PHP開発者の皆さん!この連載の第7回では、Laravel 10を使ってデータのシリアライズとリソースの変換を行う方法について詳しく解説します。APIで返されるデータを整形し、必要な形式に変換することは、クライアントに対して一貫性のあるデータを提供するために重要です。それでは、始めましょう!

1. リソースの作成

Laravelでは、Eloquentモデルをリソースクラスに変換して、APIレスポンスをカスタマイズすることができます。まず、リソースクラスを生成しましょう。

リソースクラスの生成

以下のコマンドを実行してリソースクラスを生成します。

./vendor/bin/sail artisan make:resource PostResource
Bash

これにより、app/Http/Resources/PostResource.php ファイルが生成されます。このファイルを開き、リソースの構造を定義します。

app/Http/Resources/PostResource.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

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

2. リソースコレクションの作成

複数のリソースをまとめて処理するためのリソースコレクションも作成できます。

リソースコレクションの生成

以下のコマンドを実行してリソースコレクションを生成します。

./vendor/bin/sail artisan make:resource PostCollection
Bash

app/Http/Resources/PostCollection.php ファイルが生成されます。このファイルを開き、コレクションの構造を定義します。

app/Http/Resources/PostCollection.php
namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class PostCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => url('/api/posts'),
            ],
        ];
    }
}
PHP

3. コントローラでリソースを使用する

次に、コントローラでリソースを使用してデータを返す方法を見てみましょう。

単一リソースの返却

単一のリソースを返す場合、PostResource を使用します。

app/Http/Controllers/PostController.php
namespace App\Http\Controllers\Api;

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

class PostController extends Controller
{
    public function show($id)
    {
        $post = Post::findOrFail($id);

        return new PostResource($post);
    }
}
PHP

リソースコレクションの返却

複数のリソースを返す場合、PostCollection を使用します。

app/Http/Controllers/PostController.php
namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\PostCollection;
use App\Models\Post;

class PostController extends Controller
{
    public function index()
    {
        $posts = Post::all();

        return new PostCollection($posts);
    }
}
PHP

4. カスタムレスポンスの追加

リソースクラスに追加情報を含めたい場合、リソースにメタデータやカスタムリンクを追加できます。

メタデータの追加

PostResource にメタデータを追加する例を示します。

app/Http/Resources/PostCollection.php
public function toArray($request)
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'body' => $this->body,
        'created_at' => $this->created_at->toDateTimeString(),
        'updated_at' => $this->updated_at->toDateTimeString(),
        'author' => [
            'name' => $this->user->name,
            'email' => $this->user->email,
        ],
        'links' => [
            'self' => url("/api/posts/{$this->id}"),
        ],
    ];
}
PHP

5. リソースのテスト

最後に、リソースが正しく返されるかどうかをテストします。

単一リソースのテスト

単一のリソースを返すエンドポイントのテストを追加します。

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use App\Models\Post;
use App\Models\User;

class PostApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_fetch_single_post()
    {
        $user = User::factory()->create();
        $post = Post::factory()->create(['user_id' => $user->id]);

        $response = $this->getJson("/api/posts/{$post->id}");

        $response->assertStatus(200)
                 ->assertJson([
                     'data' => [
                         'id' => $post->id,
                         'title' => $post->title,
                         'body' => $post->body,
                     ],
                 ]);
    }
}
PHP

コレクションのテスト

複数のリソースを返すエンドポイントのテストを追加します。

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use App\Models\Post;
use App\Models\User;

class PostApiTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_fetch_posts()
    {
        $user = User::factory()->create();
        $posts = Post::factory()->count(3)->create(['user_id' => $user->id]);

        $response = $this->getJson('/api/posts');

        $response->assertStatus(200)
                 ->assertJsonStructure([
                     'data' => [
                         '*' => ['id', 'title', 'body'],
                     ],
                 ]);
    }
}
PHP

6. まとめ

この記事では、Laravel 10を使ってデータのシリアライズとリソースの変換を行う方法について解説しました。リソースクラスとリソースコレクションを使用することで、APIレスポンスの一貫性を保ちつつ、必要な情報を柔軟に提供することができます。次回は、APIのパフォーマンスチューニングについて学びます。それでは、次の記事でお会いしましょう!

次の記事: 第8回 APIのテストとデバッグ

コメント

タイトルとURLをコピーしました