APIリソースとは
APIを構築するとき、EloquentモデルをそのままJSONとして返すと、隠したいカラムが漏れたり、クライアントが必要としていない大量のデータを送り付けてしまうことがあります。 Eloquent APIリソースは、モデルとJSONレスポンスの間に変換レイヤーを挟む仕組みです。toArray() メソッドで「何をどの形式でレスポンスに含めるか」を明示的に定義できます。
主なメリットは次のとおりです。
- レスポンスに含めるフィールドを完全にコントロールできる
- フィールド名の変換や値の加工をひとつの場所にまとめられる
- 条件によってフィールドを出し分けられる
- リレーションをネストして一貫した構造を保てる
リソースの作成
make:resource Artisanコマンドでリソースクラスを生成します。
app/Http/Resources ディレクトリに置かれます。
$this でモデルのプロパティに直接アクセスできます。これはリソースクラスが内部でモデルへのアクセスをプロキシしているためです。
コントローラーでの使用
定義したリソースはコントローラーやルートから返せます。toResource() メソッドを使う方法もあります。
toResource() はモデル名に基づいて対応するリソースクラス(UserResource)を自動的に探します。
デフォルトでは、レスポンスは data キーでラップされます。
リソースコレクション
複数のモデルを返す場合はcollection() メソッドを使います。
toResourceCollection() を使います。
カスタムコレクションリソース
コレクション全体にメタデータを付加したい場合は、専用のコレクションリソースを作成します。フィールドの加工と変換
toArray() 内でフィールド名の変更や値の加工ができます。
条件付きフィールド
when() — 条件に応じてフィールドを追加
特定の条件を満たすときだけフィールドを含めたい場合はwhen() を使います。
when() の条件が false のとき、そのキー自体がレスポンスから取り除かれます。
mergeWhen() — 複数フィールドをまとめて条件付き追加
同じ条件で複数のフィールドをまとめて出し分けるにはmergeWhen() を使います。
whenLoaded() — ロード済みリレーションのみ含める
リレーションがEagerロードされているときだけ含めることで、N+1問題を防ぎながら柔軟なレスポンスを作れます。whenCounted() — カウントを条件付きで含める
loadCount() で取得したリレーションのカウントを条件付きで含めます。
ネストしたリソース
リレーションを別のリソースクラスでネストすることで、一貫した構造を保てます。メタデータの追加
with() — トップレベルのメタデータ
コレクション全体にメタデータを付加するにはwith() メソッドをオーバーライドします。
additional() — 動的にメタデータを追加
コントローラー側で動的にメタデータを追加したい場合はadditional() を使います。
ページネーションとの組み合わせ
ページネーション結果をリソースに渡すだけで、meta と links が自動的に付加されます。
ページネーションレスポンスでは、
withoutWrapping() を呼んでいても data キーは必ず付きます。ページネーションの meta や links キーと共存させるためです。データラッピングの無効化
デフォルトでは最外層のリソースがdata キーにラップされます。これを無効にするには AppServiceProvider の boot() 内で withoutWrapping() を呼びます。
実践例:ユーザーAPIの実装
ユーザー管理APIを例に、リソースを使った一貫したレスポンス設計を示します。UserResource
UserController
関連ページ
Eloquentリレーション入門
リレーションの定義方法とEagerローディングを確認します。
ページネーション
ページネーション結果をAPIリソースと組み合わせる方法を確認します。