はじめに

APIを構築する際、Eloquentモデルと実際にアプリケーションのユーザーに返されるJSONレスポンスの間に変換レイヤーが必要になることがあります。たとえば、特定のユーザーのサブセットに対して特定の属性を表示したり、常に特定のリレーションシップをモデルのJSON表現に含めたりすることができます。Eloquentのリソースクラスを使用すると、モデルやモデルコレクションをJSONに表現豊かに簡単に変換できます。

もちろん、EloquentモデルやコレクションをtoJsonメソッドを使用してJSONに変換することもできますが、EloquentリソースはモデルとそのリレーションシップのJSONシリアル化に対してより詳細で堅牢な制御を提供します。

リソースの生成

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

  1. php artisan make:resource UserResource

リソースコレクション

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

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

  1. php artisan make:resource User --collection
  2. php artisan make:resource UserCollection

概念の概要

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

リソースを書く際に利用可能なすべてのオプションに飛び込む前に、まずLaravel内でリソースがどのように使用されるかを高レベルで見てみましょう。リソースクラスは、JSON構造に変換する必要がある単一のモデルを表します。たとえば、ここにシンプルなUserResourceリソースクラスがあります:

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\Resources\Json\JsonResource;
  5. class UserResource extends JsonResource
  6. {
  7. /**
  8. * Transform the resource into an array.
  9. *
  10. * @return array<string, mixed>
  11. */
  12. public function toArray(Request $request): array
  13. {
  14. return [
  15. 'id' => $this->id,
  16. 'name' => $this->name,
  17. 'email' => $this->email,
  18. 'created_at' => $this->created_at,
  19. 'updated_at' => $this->updated_at,
  20. ];
  21. }
  22. }

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

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

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/user/{id}', function (string $id) {
  4. return new UserResource(User::findOrFail($id));
  5. });

リソースコレクション

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

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/users', function () {
  4. return UserResource::collection(User::all());
  5. });

これは、コレクションと共に返される必要があるカスタムメタデータの追加を許可しません。リソースコレクションレスポンスをカスタマイズしたい場合は、コレクションを表す専用のリソースを作成できます:

  1. php artisan make:resource UserCollection

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\Resources\Json\ResourceCollection;
  5. class UserCollection extends ResourceCollection
  6. {
  7. /**
  8. * Transform the resource collection into an array.
  9. *
  10. * @return array<int|string, mixed>
  11. */
  12. public function toArray(Request $request): array
  13. {
  14. return [
  15. 'data' => $this->collection,
  16. 'links' => [
  17. 'self' => 'link-value',
  18. ],
  19. ];
  20. }
  21. }

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

  1. use App\Http\Resources\UserCollection;
  2. use App\Models\User;
  3. Route::get('/users', function () {
  4. return new UserCollection(User::all());
  5. });

コレクションキーの保持

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Resources\Json\JsonResource;
  4. class UserResource extends JsonResource
  5. {
  6. /**
  7. * Indicates if the resource's collection keys should be preserved.
  8. *
  9. * @var bool
  10. */
  11. public $preserveKeys = true;
  12. }
  1. ``````php
  2. use App\Http\Resources\UserResource;
  3. use App\Models\User;
  4. Route::get('/users', function () {
  5. return UserResource::collection(User::all()->keyBy->id);
  6. });
  7. `

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

通常、リソースコレクションの$this->collectionプロパティは、コレクションの各アイテムをその単数リソースクラスにマッピングした結果で自動的に埋められます。単数リソースクラスは、クラス名の末尾のCollection部分を除いたコレクションのクラス名と見なされます。さらに、個人の好みに応じて、単数リソースクラスはResourceでサフィックスされる場合とされない場合があります。

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Resources\Json\ResourceCollection;
  4. class UserCollection extends ResourceCollection
  5. {
  6. /**
  7. * The resource that this resource collects.
  8. *
  9. * @var string
  10. */
  11. public $collects = Member::class;
  12. }

リソースの作成

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

リソースは、特定のモデルを配列に変換する必要があるだけです。したがって、各リソースには、モデルの属性をAPIフレンドリーな配列に変換するtoArrayメソッドが含まれています。この配列は、アプリケーションのルートやコントローラーから返されることができます:

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\Resources\Json\JsonResource;
  5. class UserResource extends JsonResource
  6. {
  7. /**
  8. * Transform the resource into an array.
  9. *
  10. * @return array<string, mixed>
  11. */
  12. public function toArray(Request $request): array
  13. {
  14. return [
  15. 'id' => $this->id,
  16. 'name' => $this->name,
  17. 'email' => $this->email,
  18. 'created_at' => $this->created_at,
  19. 'updated_at' => $this->updated_at,
  20. ];
  21. }
  22. }

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

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/user/{id}', function (string $id) {
  4. return new UserResource(User::findOrFail($id));
  5. });

リレーションシップ

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

  1. use App\Http\Resources\PostResource;
  2. use Illuminate\Http\Request;
  3. /**
  4. * Transform the resource into an array.
  5. *
  6. * @return array<string, mixed>
  7. */
  8. public function toArray(Request $request): array
  9. {
  10. return [
  11. 'id' => $this->id,
  12. 'name' => $this->name,
  13. 'email' => $this->email,
  14. 'posts' => PostResource::collection($this->posts),
  15. 'created_at' => $this->created_at,
  16. 'updated_at' => $this->updated_at,
  17. ];
  18. }

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

リソースコレクション

リソースは単一のモデルを配列に変換しますが、リソースコレクションはモデルのコレクションを配列に変換します。ただし、すべてのリソースがcollectionメソッドを提供しているため、各モデルに対してリソースコレクションクラスを定義する必要はありません。このメソッドは、即席のリソースコレクションをその場で生成します:

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/users', function () {
  4. return UserResource::collection(User::all());
  5. });

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Request;
  4. use Illuminate\Http\Resources\Json\ResourceCollection;
  5. class UserCollection extends ResourceCollection
  6. {
  7. /**
  8. * Transform the resource collection into an array.
  9. *
  10. * @return array<string, mixed>
  11. */
  12. public function toArray(Request $request): array
  13. {
  14. return [
  15. 'data' => $this->collection,
  16. 'links' => [
  17. 'self' => 'link-value',
  18. ],
  19. ];
  20. }
  21. }

単数リソースと同様に、リソースコレクションはルートやコントローラーから直接返されることができます:

  1. use App\Http\Resources\UserCollection;
  2. use App\Models\User;
  3. Route::get('/users', function () {
  4. return new UserCollection(User::all());
  5. });

データラッピング

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

  1. {
  2. "data": [
  3. {
  4. "id": 1,
  5. "name": "Eladio Schroeder Sr.",
  6. "email": ""
  7. },
  8. {
  9. "id": 2,
  10. "name": "Liliana Mayert",
  11. "email": ""
  12. }
  13. ]
  14. }

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

  1. <?php
  2. namespace App\Providers;
  3. use Illuminate\Http\Resources\Json\JsonResource;
  4. use Illuminate\Support\ServiceProvider;
  5. class AppServiceProvider extends ServiceProvider
  6. {
  7. /**
  8. * Register any application services.
  9. */
  10. public function register(): void
  11. {
  12. // ...
  13. }
  14. /**
  15. * Bootstrap any application services.
  16. */
  17. public function boot(): void
  18. {
  19. JsonResource::withoutWrapping();
  20. }
  21. }
  1. <a name="wrapping-nested-resources"></a>
  2. #### ネストされたリソースのラッピング
  3. リソースのリレーションシップがどのようにラップされるかを決定する自由があります。すべてのリソースコレクションをネストに関係なく`````data`````キーでラップしたい場合は、各リソースのリソースコレクションクラスを定義し、`````data`````キー内でコレクションを返す必要があります。
  4. 最外層のリソースが2つの`````data`````キーでラップされるかどうか疑問に思うかもしれません。心配しないでください、Laravelはリソースが誤って二重にラップされることを決して許可しないので、変換しているリソースコレクションのネストレベルについて心配する必要はありません:
  5. ``````php
  6. <?php
  7. namespace App\Http\Resources;
  8. use Illuminate\Http\Resources\Json\ResourceCollection;
  9. class CommentsCollection extends ResourceCollection
  10. {
  11. /**
  12. * Transform the resource collection into an array.
  13. *
  14. * @return array<string, mixed>
  15. */
  16. public function toArray(Request $request): array
  17. {
  18. return ['data' => $this->collection];
  19. }
  20. }
  21. `

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

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

  1. {
  2. "data": [
  3. {
  4. "id": 1,
  5. "name": "Eladio Schroeder Sr.",
  6. "email": ""
  7. },
  8. {
  9. "id": 2,
  10. "name": "Liliana Mayert",
  11. "email": ""
  12. }
  13. ],
  14. "links":{
  15. "first": "http://example.com/users?page=1",
  16. "last": "http://example.com/users?page=1",
  17. "prev": null,
  18. "next": null
  19. },
  20. "meta":{
  21. "current_page": 1,
  22. "from": 1,
  23. "last_page": 1,
  24. "path": "http://example.com/users",
  25. "per_page": 15,
  26. "to": 10,
  27. "total": 10
  28. }
  29. }

ページネーション

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

  1. use App\Http\Resources\UserCollection;
  2. use App\Models\User;
  3. Route::get('/users', function () {
  4. return new UserCollection(User::paginate());
  5. });

ページネートされたレスポンスには常にmetaおよびlinksキーが含まれており、ページネーターの状態に関する情報が含まれています:

  1. {
  2. "data": [
  3. {
  4. "id": 1,
  5. "name": "Eladio Schroeder Sr.",
  6. "email": ""
  7. },
  8. {
  9. "id": 2,
  10. "name": "Liliana Mayert",
  11. "email": ""
  12. }
  13. ],
  14. "links":{
  15. "first": "http://example.com/users?page=1",
  16. "last": "http://example.com/users?page=1",
  17. "prev": null,
  18. "next": null
  19. },
  20. "meta":{
  21. "current_page": 1,
  22. "from": 1,
  23. "last_page": 1,
  24. "path": "http://example.com/users",
  25. "per_page": 15,
  26. "to": 10,
  27. "total": 10
  28. }
  29. }

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

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

  1. /**
  2. * Customize the pagination information for the resource.
  3. *
  4. * @param \Illuminate\Http\Request $request
  5. * @param array $paginated
  6. * @param array $default
  7. * @return array
  8. */
  9. public function paginationInformation($request, $paginated, $default)
  10. {
  11. $default['links']['custom'] = 'https://example.com';
  12. return $default;
  13. }

条件付き属性

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

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. return [
  9. 'id' => $this->id,
  10. 'name' => $this->name,
  11. 'email' => $this->email,
  12. 'secret' => $this->when($request->user()->isAdmin(), 'secret-value'),
  13. 'created_at' => $this->created_at,
  14. 'updated_at' => $this->updated_at,
  15. ];
  16. }

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

  1. ``````php
  2. 'secret' => $this->when($request->user()->isAdmin(), function () {
  3. return 'secret-value';
  4. }),
  5. `
  1. ``````php
  2. 'name' => $this->whenHas('name'),
  3. `

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

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

条件付き属性のマージ

時には、同じ条件に基づいてリソースレスポンスに含めるべきいくつかの属性がある場合があります。この場合、mergeWhenメソッドを使用して、与えられた条件がtrueである場合にのみレスポンスに属性を含めることができます:

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. return [
  9. 'id' => $this->id,
  10. 'name' => $this->name,
  11. 'email' => $this->email,
  12. $this->mergeWhen($request->user()->isAdmin(), [
  13. 'first-secret' => 'value',
  14. 'second-secret' => 'value',
  15. ]),
  16. 'created_at' => $this->created_at,
  17. 'updated_at' => $this->updated_at,
  18. ];
  19. }

再度、与えられた条件がfalseである場合、これらの属性はクライアントに送信される前にリソースレスポンスから削除されます。

  1. <a name="conditional-relationships"></a>
  2. ### 条件付きリレーションシップ
  3. 属性を条件付きでロードすることに加えて、モデルにリレーションシップがすでにロードされているかどうかに基づいてリソースレスポンスにリレーションシップを条件付きで含めることができます。これにより、コントローラーがモデルにどのリレーションシップをロードするかを決定し、リソースは実際にロードされた場合にのみそれらを簡単に含めることができます。最終的に、これによりリソース内で「N+1」クエリの問題を回避しやすくなります。
  4. `````whenLoaded`````メソッドを使用して、リレーションシップを条件付きでロードできます。不要にリレーションシップをロードしないように、このメソッドはリレーションシップ自体ではなく、リレーションシップの名前を受け取ります:
  5. ``````php
  6. use App\Http\Resources\PostResource;
  7. /**
  8. * Transform the resource into an array.
  9. *
  10. * @return array<string, mixed>
  11. */
  12. public function toArray(Request $request): array
  13. {
  14. return [
  15. 'id' => $this->id,
  16. 'name' => $this->name,
  17. 'email' => $this->email,
  18. 'posts' => PostResource::collection($this->whenLoaded('posts')),
  19. 'created_at' => $this->created_at,
  20. 'updated_at' => $this->updated_at,
  21. ];
  22. }
  23. `

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

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

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

  1. new UserResource($user->loadCount('posts'));
  1. ``````php
  2. /**
  3. * Transform the resource into an array.
  4. *
  5. * @return array<string, mixed>
  6. */
  7. public function toArray(Request $request): array
  8. {
  9. return [
  10. 'id' => $this->id,
  11. 'name' => $this->name,
  12. 'email' => $this->email,
  13. 'posts_count' => $this->whenCounted('posts'),
  14. 'created_at' => $this->created_at,
  15. 'updated_at' => $this->updated_at,
  16. ];
  17. }
  18. `

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

  1. ``````php
  2. 'words_avg' => $this->whenAggregated('posts', 'words', 'avg'),
  3. 'words_sum' => $this->whenAggregated('posts', 'words', 'sum'),
  4. 'words_min' => $this->whenAggregated('posts', 'words', 'min'),
  5. 'words_max' => $this->whenAggregated('posts', 'words', 'max'),
  6. `

条件付きピボット情報

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

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. return [
  9. 'id' => $this->id,
  10. 'name' => $this->name,
  11. 'expires_at' => $this->whenPivotLoaded('role_user', function () {
  12. return $this->pivot->expires_at;
  13. }),
  14. ];
  15. }

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

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

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

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. return [
  9. 'id' => $this->id,
  10. 'name' => $this->name,
  11. 'expires_at' => $this->whenPivotLoadedAs('subscription', 'role_user', function () {
  12. return $this->subscription->expires_at;
  13. }),
  14. ];
  15. }

メタデータの追加

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

  1. /**
  2. * Transform the resource into an array.
  3. *
  4. * @return array<string, mixed>
  5. */
  6. public function toArray(Request $request): array
  7. {
  8. return [
  9. 'data' => $this->collection,
  10. 'links' => [
  11. 'self' => 'link-value',
  12. ],
  13. ];
  14. }

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

トップレベルメタデータ

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\Resources\Json\ResourceCollection;
  4. class UserCollection extends ResourceCollection
  5. {
  6. /**
  7. * Transform the resource collection into an array.
  8. *
  9. * @return array<string, mixed>
  10. */
  11. public function toArray(Request $request): array
  12. {
  13. return parent::toArray($request);
  14. }
  15. /**
  16. * Get additional data that should be returned with the resource array.
  17. *
  18. * @return array<string, mixed>
  19. */
  20. public function with(Request $request): array
  21. {
  22. return [
  23. 'meta' => [
  24. 'key' => 'value',
  25. ],
  26. ];
  27. }
  28. }

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

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

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

リソースレスポンス

すでに読んだように、リソースはルートやコントローラーから直接返されることがあります:

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/user/{id}', function (string $id) {
  4. return new UserResource(User::findOrFail($id));
  5. });

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

  1. use App\Http\Resources\UserResource;
  2. use App\Models\User;
  3. Route::get('/user', function () {
  4. return (new UserResource(User::find(1)))
  5. ->response()
  6. ->header('X-Value', 'True');
  7. });

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

  1. <?php
  2. namespace App\Http\Resources;
  3. use Illuminate\Http\JsonResponse;
  4. use Illuminate\Http\Request;
  5. use Illuminate\Http\Resources\Json\JsonResource;
  6. class UserResource extends JsonResource
  7. {
  8. /**
  9. * Transform the resource into an array.
  10. *
  11. * @return array<string, mixed>
  12. */
  13. public function toArray(Request $request): array
  14. {
  15. return [
  16. 'id' => $this->id,
  17. ];
  18. }
  19. /**
  20. * Customize the outgoing response for the resource.
  21. */
  22. public function withResponse(Request $request, JsonResponse $response): void
  23. {
  24. $response->header('X-Value', 'True');
  25. }
  26. }