Skip to content

Eloquent: API Resources

はじめに

APIを構築する際、Eloquentモデルと実際にアプリケーションのユーザーに返されるJSONレスポンスの間に変換レイヤーが必要になる場合があります。例えば、特定の属性を一部のユーザーに表示し、他のユーザーには表示しないようにしたい場合や、モデルのJSON表現に常に特定のリレーションシップを含めたい場合があります。Eloquentのリソースクラスを使用すると、モデルとモデルコレクションをJSONに簡単かつ表現力豊かに変換できます。

もちろん、EloquentモデルやコレクションをtoJsonメソッドを使用してJSONに変換することは常に可能です。しかし、EloquentリソースはモデルとそのリレーションシップのJSONシリアライズをより細かく、堅牢に制御できます。

リソースの生成

リソースクラスを生成するには、make:resource Artisanコマンドを使用できます。デフォルトでは、リソースはアプリケーションのapp/Http/Resourcesディレクトリに配置されます。リソースはIlluminate\Http\Resources\Json\JsonResourceクラスを拡張します。

php artisan make:resource UserResource

リソースコレクション

個々のモデルを変換するリソースを生成するだけでなく、モデルのコレクションを変換する責任を持つリソースを生成することもできます。これにより、JSONレスポンスにリンクやその他のメタ情報を含めることができます。

リソースコレクションを作成するには、リソースを作成する際に--collectionフラグを使用するか、リソース名にCollectionという単語を含めることで、Laravelにコレクションリソースを作成するよう指示できます。コレクションリソースはIlluminate\Http\Resources\Json\ResourceCollectionクラスを拡張します。

php artisan make:resource User --collection

php artisan make:resource UserCollection

概念の概要

Note

これはリソースとリソースコレクションの概要です。リソースが提供するカスタマイズとパワーを深く理解するために、このドキュメントの他のセクションを読むことを強くお勧めします。

リソースがLaravel内でどのように使用されるかを詳細に説明する前に、まずリソースの使い方を高レベルで見てみましょう。リソースクラスは、単一のモデルをJSON構造に変換する必要があることを表します。例えば、以下はシンプルなUserResourceリソースクラスです。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * リソースを配列に変換します。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

すべてのリソースクラスは、リソースがルートまたはコントローラーメソッドからレスポンスとして返されるときにJSONに変換されるべき属性の配列を返すtoArrayメソッドを定義します。

$this変数からモデルのプロパティに直接アクセスできることに注意してください。これは、リソースクラスが基礎となるモデルへのプロパティとメソッドのアクセスを自動的にプロキシするためです。リソースが定義されると、ルートまたはコントローラーから返すことができます。リソースは、コンストラクターを介して基礎となるモデルインスタンスを受け取ります。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/user/{id}', function (string $id) {
    return new UserResource(User::findOrFail($id));
});

リソースコレクション

リソースのコレクションまたはページネーションされたレスポンスを返す場合、ルートまたはコントローラーでリソースインスタンスを作成する際に、リソースクラスが提供するcollectionメソッドを使用する必要があります。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/users', function () {
    return UserResource::collection(User::all());
});

これにより、コレクションに必要なカスタムメタデータの追加ができなくなります。リソースコレクションのレスポンスをカスタマイズしたい場合は、コレクションを表す専用のリソースを作成できます。

php artisan make:resource UserCollection

リソースコレクションクラスが生成されたら、レスポンスに含めるべきメタデータを簡単に定義できます。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * リソースコレクションを配列に変換します。
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

リソースコレクションを定義した後、ルートまたはコントローラーから返すことができます。

use App\Http\Resources\UserCollection;
use App\Models\User;

Route::get('/users', function () {
    return new UserCollection(User::all());
});

コレクションキーの保持

ルートからリソースコレクションを返すと、Laravelはコレクションのキーをリセットして数値順に並べます。ただし、コレクションの元のキーを保持するかどうかを示すpreserveKeysプロパティをリソースクラスに追加できます。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * リソースのコレクションキーを保持するかどうかを示します。
     *
     * @var bool
     */
    public $preserveKeys = true;
}

preserveKeysプロパティがtrueに設定されている場合、コレクションのキーはルートまたはコントローラーから返されるときに保持されます。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/users', function () {
    return UserResource::collection(User::all()->keyBy->id);
});

基礎となるリソースクラスのカスタマイズ

通常、リソースコレクションの$this->collectionプロパティは、コレクションの各アイテムを単一のリソースクラスにマッピングした結果で自動的に設定されます。単一のリソースクラスは、コレクションのクラス名から末尾のCollection部分を除いたものと推定されます。さらに、個人的な好みに応じて、単一のリソースクラスにResourceという接尾辞が付く場合と付かない場合があります。

例えば、UserCollectionは指定されたユーザーインスタンスをUserResourceリソースにマッピングしようとします。この動作をカスタマイズするには、リソースコレクションの$collectsプロパティをオーバーライドできます。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * このリソースが収集するリソース。
     *
     * @var string
     */
    public $collects = Member::class;
}

リソースの記述

Note

概念の概要をまだ読んでいない場合は、このドキュメントを進める前に読むことを強くお勧めします。

リソースは、指定されたモデルを配列に変換する必要があります。したがって、各リソースには、モデルの属性をAPIに適した配列に変換するtoArrayメソッドが含まれています。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * リソースを配列に変換します。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }
}

リソースが定義されると、ルートまたはコントローラーから直接返すことができます。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/user/{id}', function (string $id) {
    return new UserResource(User::findOrFail($id));
});

リレーションシップ

レスポンスに関連リソースを含めたい場合は、リソースのtoArrayメソッドが返す配列にそれらを追加できます。この例では、PostResourceリソースのcollectionメソッドを使用して、ユーザーのブログ投稿をリソースレスポンスに追加します。

use App\Http\Resources\PostResource;
use Illuminate\Http\Request;

/**
 * リソースを配列に変換する。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => PostResource::collection($this->posts),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

Note

リレーションが既にロードされている場合にのみリレーションを含めたい場合は、条件付きリレーションに関するドキュメントを確認してください。

リソースコレクション

リソースは単一のモデルを配列に変換しますが、リソースコレクションはモデルのコレクションを配列に変換します。しかし、すべてのモデルに対してリソースコレクションクラスを定義する必要はありません。すべてのリソースは、「アドホック」なリソースコレクションを即座に生成するための collection メソッドを提供しています。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/users', function () {
    return UserResource::collection(User::all());
});

ただし、コレクションとともに返されるメタデータをカスタマイズする必要がある場合は、独自のリソースコレクションを定義する必要があります。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * リソースコレクションを配列に変換する。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

単一のリソースと同様に、リソースコレクションはルートまたはコントローラーから直接返すことができます。

use App\Http\Resources\UserCollection;
use App\Models\User;

Route::get('/users', function () {
    return new UserCollection(User::all());
});

データのラッピング

デフォルトでは、リソースレスポンスがJSONに変換されるとき、最も外側のリソースは data キーでラップされます。したがって、典型的なリソースコレクションレスポンスは次のようになります。

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com"
        }
    ]
}

最も外側のリソースのラッピングを無効にしたい場合は、基本の Illuminate\Http\Resources\Json\JsonResource クラスで withoutWrapping メソッドを呼び出す必要があります。通常、このメソッドは AppServiceProvider またはアプリケーションへのすべてのリクエストでロードされる他のサービスプロバイダから呼び出す必要があります。

<?php

namespace App\Providers;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * 任意のアプリケーションサービスを登録する。
     */
    public function register(): void
    {
        // ...
    }

    /**
     * 任意のアプリケーションサービスを起動する。
     */
    public function boot(): void
    {
        JsonResource::withoutWrapping();
    }
}

Warning

withoutWrapping メソッドは最も外側のレスポンスにのみ影響し、自分でリソースコレクションに手動で追加した data キーは削除しません。

ネストされたリソースのラッピング

リソースのリレーションがどのようにラップされるかを自由に決定できます。すべてのリソースコレクションを data キーでラップしたい場合、ネストに関係なく、各リソースに対してリソースコレクションクラスを定義し、コレクションを data キー内で返す必要があります。

最も外側のリソースが2つの data キーでラップされるかどうかを心配する必要はありません。Laravelはリソースが誤って二重にラップされることを防ぐため、変換しているリソースコレクションのネストレベルについて心配する必要はありません。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class CommentsCollection extends ResourceCollection
{
    /**
     * リソースコレクションを配列に変換する。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return ['data' => $this->collection];
    }
}

データのラッピングとページネーション

リソースレスポンスを介してページネーションされたコレクションを返す場合、Laravelは withoutWrapping メソッドが呼び出された場合でも、リソースデータを data キーでラップします。これは、ページネータの状態に関する情報を含む meta および links キーをページネーションレスポンスに常に含めるためです。

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com"
        }
    ],
    "links":{
        "first": "http://example.com/users?page=1",
        "last": "http://example.com/users?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/users",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

ページネーション

Laravelのページネータインスタンスをリソースの collection メソッドまたはカスタムリソースコレクションに渡すことができます。

use App\Http\Resources\UserCollection;
use App\Models\User;

Route::get('/users', function () {
    return new UserCollection(User::paginate());
});

ページネーションされたレスポンスには、ページネータの状態に関する情報を含む meta および links キーが常に含まれます。

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com"
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com"
        }
    ],
    "links":{
        "first": "http://example.com/users?page=1",
        "last": "http://example.com/users?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/users",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}

ページネーション情報のカスタマイズ

ページネーションレスポンスの links または meta キーに含まれる情報をカスタマイズしたい場合は、リソースに paginationInformation メソッドを定義できます。このメソッドは $paginated データと $default 情報の配列を受け取ります。これは links および meta キーを含む配列です。

/**
 * リソースのページネーション情報をカスタマイズする。
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  array $paginated
 * @param  array $default
 * @return array
 */
public function paginationInformation($request, $paginated, $default)
{
    $default['links']['custom'] = 'https://example.com';

    return $default;
}

条件付き属性

特定の条件が満たされた場合にのみ属性をリソースレスポンスに含めたい場合があります。たとえば、現在のユーザーが「管理者」である場合にのみ値を含めたい場合です。Laravelはこの状況を支援するためのさまざまなヘルパーメソッドを提供しています。when メソッドは、条件付きで属性をリソースレスポンスに追加するために使用できます。

/**
 * リソースを配列に変換する。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'secret' => $this->when($request->user()->isAdmin(), 'secret-value'),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

この例では、認証されたユーザーの isAdmin メソッドが true を返す場合にのみ、secret キーが最終的なリソースレスポンスに返されます。メソッドが false を返す場合、secret キーはクライアントに送信される前にリソースレスポンスから削除されます。when メソッドを使用すると、配列を構築する際に条件文に頼ることなく、リソースを表現的に定義できます。

when メソッドは、2番目の引数としてクロージャも受け入れ、指定された条件が true の場合にのみ結果の値を計算できます。

'secret' => $this->when($request->user()->isAdmin(), function () {
    return 'secret-value';
}),

whenHas メソッドは、属性が実際に基礎となるモデルに存在する場合に属性を含めるために使用できます。

'name' => $this->whenHas('name'),

さらに、whenNotNull メソッドは、属性が null でない場合にリソースレスポンスに属性を含めるために使用できます。

'name' => $this->whenNotNull($this->name),

条件付き属性のマージ

条件付き属性をマージする必要がある場合があります。たとえば、現在のユーザーが管理者である場合にのみ、特定の配列をリソースレスポンスに含めたい場合です。Laravelはこのための mergeWhen メソッドを提供しています。このメソッドは、指定された条件が true の場合にのみ、属性をレスポンスに含めます。

/**
 * リソースを配列に変換する。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
        $this->mergeWhen($request->user()->isAdmin(), [
            'first-secret' => 'value',
            'second-secret' => 'value',
        ]),
    ];
}

Warning

このメソッドは、ソートされていない配列で使用する場合にのみ適しています。mergeWhen メソッドをソートされた配列で使用すると、期待される出力順序が壊れる可能性があります。

場合によっては、同じ条件に基づいてリソースレスポンスにのみ含まれるべき複数の属性があるかもしれません。この場合、mergeWhenメソッドを使用して、指定された条件がtrueの場合にのみ属性をレスポンスに含めることができます。

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        $this->mergeWhen($request->user()->isAdmin(), [
            'first-secret' => 'value',
            'second-secret' => 'value',
        ]),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

繰り返しますが、指定された条件がfalseの場合、これらの属性はクライアントに送信される前にリソースレスポンスから削除されます。

Warning

mergeWhenメソッドは、文字列キーと数値キーが混在する配列内で使用してはいけません。さらに、順序付けられていない数値キーを持つ配列内でも使用してはいけません。

条件付きリレーションシップ

属性の条件付き読み込みに加えて、モデルにリレーションシップが既に読み込まれているかどうかに基づいて、リソースレスポンスにリレーションシップを条件付きで含めることができます。これにより、コントローラーがモデルに読み込むべきリレーションシップを決定し、リソースは実際に読み込まれた場合にのみそれらを簡単に含めることができます。最終的に、リソース内の「N+1」クエリ問題を簡単に回避できます。

whenLoadedメソッドを使用して、リレーションシップを条件付きで読み込むことができます。不要なリレーションシップの読み込みを避けるために、このメソッドはリレーションシップ自体ではなく、リレーションシップの名前を受け取ります。

use App\Http\Resources\PostResource;

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts' => PostResource::collection($this->whenLoaded('posts')),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

この例では、リレーションシップが読み込まれていない場合、postsキーはクライアントに送信される前にリソースレスポンスから削除されます。

条件付きリレーションシップのカウント

リレーションシップの条件付き読み込みに加えて、モデルにリレーションシップのカウントが読み込まれているかどうかに基づいて、リソースレスポンスにリレーションシップの「カウント」を条件付きで含めることができます。

new UserResource($user->loadCount('posts'));

whenCountedメソッドを使用して、リソースレスポンスにリレーションシップのカウントを条件付きで含めることができます。このメソッドは、リレーションシップのカウントが存在しない場合に不要な属性を含めないようにします。

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        'posts_count' => $this->whenCounted('posts'),
        'created_at' => $this->created_at,
        'updated_at' => $this->updated_at,
    ];
}

この例では、postsリレーションシップのカウントが読み込まれていない場合、posts_countキーはクライアントに送信される前にリソースレスポンスから削除されます。

他の集計タイプ、例えばavgsumminmaxも、whenAggregatedメソッドを使用して条件付きで読み込むことができます。

'words_avg' => $this->whenAggregated('posts', 'words', 'avg'),
'words_sum' => $this->whenAggregated('posts', 'words', 'sum'),
'words_min' => $this->whenAggregated('posts', 'words', 'min'),
'words_max' => $this->whenAggregated('posts', 'words', 'max'),

条件付きピボット情報

リソースレスポンスにリレーションシップ情報を条件付きで含めることに加えて、whenPivotLoadedメソッドを使用して、多対多リレーションシップの中間テーブルからデータを条件付きで含めることができます。whenPivotLoadedメソッドは、ピボットテーブルの名前を最初の引数として受け取ります。2番目の引数は、ピボット情報がモデルで利用可能な場合に返される値を返すクロージャである必要があります。

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'expires_at' => $this->whenPivotLoaded('role_user', function () {
            return $this->pivot->expires_at;
        }),
    ];
}

リレーションシップがカスタム中間テーブルモデルを使用している場合、中間テーブルモデルのインスタンスをwhenPivotLoadedメソッドの最初の引数として渡すことができます。

'expires_at' => $this->whenPivotLoaded(new Membership, function () {
    return $this->pivot->expires_at;
}),

中間テーブルがpivot以外のアクセサを使用している場合、whenPivotLoadedAsメソッドを使用できます。

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () {
            return $this->subscription->expires_at;
        }),
    ];
}

メタデータの追加

一部のJSON API標準では、リソースやリソースコレクションのレスポンスにメタデータを追加する必要があります。これには、リソースや関連リソースへのlinksや、リソース自体に関するメタデータが含まれることがあります。リソースに追加のメタデータを返す必要がある場合は、toArrayメソッドに含めます。例えば、リソースコレクションを変換する際にlinks情報を含めることができます。

/**
 * リソースを配列に変換します。
 *
 * @return array<string, mixed>
 */
public function toArray(Request $request): array
{
    return [
        'data' => $this->collection,
        'links' => [
            'self' => 'link-value',
        ],
    ];
}

リソースから追加のメタデータを返す場合、ページネーションレスポンスを返す際にLaravelが自動的に追加するlinksmetaキーを誤って上書きすることを心配する必要はありません。定義した追加のlinksは、ページネーターによって提供されるリンクとマージされます。

トップレベルのメタデータ

リソースが返される最も外側のリソースである場合にのみ、特定のメタデータをリソースレスポンスに含めたい場合があります。通常、これにはレスポンス全体に関するメタ情報が含まれます。このメタデータを定義するには、リソースクラスにwithメソッドを追加します。このメソッドは、リソースが最も外側のリソースとして変換される場合にのみ、リソースレスポンスに含まれるメタデータの配列を返す必要があります。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class UserCollection extends ResourceCollection
{
    /**
     * リソースコレクションを配列に変換します。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return parent::toArray($request);
    }

    /**
     * リソース配列と共に返されるべき追加データを取得します。
     *
     * @return array<string, mixed>
     */
    public function with(Request $request): array
    {
        return [
            'meta' => [
                'key' => 'value',
            ],
        ];
    }
}

リソース構築時にメタデータを追加

ルートまたはコントローラーでリソースインスタンスを構築する際に、トップレベルのデータを追加することもできます。additionalメソッドは、すべてのリソースで利用可能で、リソースレスポンスに追加されるべきデータの配列を受け取ります。

return (new UserCollection(User::all()->load('roles')))
                ->additional(['meta' => [
                    'key' => 'value',
                ]]);

リソースレスポンス

すでに読んだように、リソースはルートやコントローラーから直接返すことができます。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/user/{id}', function (string $id) {
    return new UserResource(User::findOrFail($id));
});

ただし、クライアントに送信される前に送信HTTPレスポンスをカスタマイズする必要がある場合があります。これを実現するには2つの方法があります。まず、リソースにresponseメソッドをチェーンすることができます。このメソッドはIlluminate\Http\JsonResponseインスタンスを返し、レスポンスのヘッダーを完全に制御できます。

use App\Http\Resources\UserResource;
use App\Models\User;

Route::get('/user', function () {
    return (new UserResource(User::find(1)))
                ->response()
                ->header('X-Value', 'True');
});

あるいは、リソース自体にwithResponseメソッドを定義することもできます。このメソッドは、リソースがレスポンスとして最も外側のリソースとして返されるときに呼び出されます。

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * リソースを配列に変換します。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
            'created_at' => $this->created_at,
            'updated_at' => $this->updated_at,
        ];
    }

    /**
     * リソースレスポンスをカスタマイズします。
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Illuminate\Http\Response  $response
     * @return void
     */
    public function withResponse(Request $request, $response)
    {
        $response->header('X-Value', 'True');
    }
}
namespace App\Http\Resources;

use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * リソースを配列に変換します。
     *
     * @return array<string, mixed>
     */
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
        ];
    }

    /**
     * リソースの送信レスポンスをカスタマイズします。
     */
    public function withResponse(Request $request, JsonResponse $response): void
    {
        $response->header('X-Value', 'True');
    }
}

ユーザーノート