0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Laravel APIのResource,Collectionとjson()について

Posted at

はじめに

初めての投稿となりますので間違い等ありましたらご指摘いただけると幸いです。

LaravelのAPIでreturnする時に

  • json()で返す方法
  • new UserCollectionの様に返す方法

上記の方法があるのは知っていたけど普段はMPA構成を作ることが多くあまり詳細について知らなかったので調べてみました。

結論

ざっくり以下の様な使い分けで良いのかなと思いました。

json()

  • シンプルに返したい場合
  • モデルと関係ない場合
  • 外部APIのレスポンスを返す時

Resource,Collection

  • モデルを返す時
  • 複数箇所で一貫したレスポンスを返したい時
  • データ整形をしたい時
  • whenLoadedでN+1の回避 (記事内では割愛します

以下はサンプルです。

json()の場合

Route::get('/', function () {
    // 第二引数にstatus codeを指定できる(defaultは200)
    return response()->json(["user" => User::all()], 200]);
});

// return
[
  {
    "id": 1,
    "name": "user1",
    "email": "user1@user.com"
  },
  {
    "id": 2,
    "name": "user2",
    "email": "user2@user.com"
  }
]

Resource,Collectionの場合

準備

php artisan make:resource UserResourceでリソースファイルを作成

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

class UserResource extends JsonResource
{
   public function toArray(Request $request): array
    {
        return parent::toArray($request);
    }
}

toArrayをカスタムしてreturnする項目を変更できます。

// UserResource
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'name' => $this->name,
        'email' => $this->email,
        // 必要に応じて、関連データや条件付きの属性を追加(割愛)
        // 'posts' => PostResource::collection($this->whenLoaded('posts')),
    ];
}

呼び出し

Route::get('/', function () {
    return new UserResource(User::find(1));
});

// return
{
  "data": {
    "id": 1,
    "name": "user1",
    "email": "user1@user.com"
  }
}

dataキーでラップされて出力されます。dataをなくしたい場合はAppServiceProviderを以下の様にします。

// AppServiceProvider
public function boot()
{
    JsonResource::withoutWrapping();
}

// return
{
  "id": 1,
  "name": "user1",
  "email": "user1@user.com"
}

collectionについて

JsonResourceクラスによって提供されるcollectionメソッドを使用する事で以下の様にコレクションを返します。

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

// return
{
  "data": [
    {
      "id": 1,
      "name": "user1",
      "email": "user1@user.com"
    },
    {
      "id": 2,
      "name": "user2",
      "email": "user2@user.com"
    }
  ]
}

別途php artisan make:resource UserCollectionでリソースコレクションを返すクラスも生成できます。カスタムする場合は以下の様にします。

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

class UserCollection extends ResourceCollection
{
    public function toArray($request)
    {
        return [
            'data' => $this->collection,
            'links' => [
                'self' => 'link-value',
            ],
        ];
    }
}

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

// return
{
  "data": [
    {
      "id": 1,
      "name": "user1",
      "email": "user1@user.com"
    },
    {
      "id": 2,
      "name": "user2",
      "email": "user2@user.com"
    }
  ],
  "links": {
    "self": "link-value"
  }
}

UserCollection内のtoArrayで配列の加工ができます。上記ではlinksキーを追加しています。
またUserResource,UserCollectionを用意してcollection内で$collectsをオーバーライドするとresourceと同じ内容を返すことができます。

// UserCollection
class UserCollection extends ResourceCollection
{
    public $collects = UserResource::class;

    public function toArray(Request $request): array
    {
        // ...
    }
}

// UserResource
class UserResource extends JsonResource
{
    public function toArray(Request $request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
        ];
    }
}

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

// return
{
  "data": [
    {
      "id": 1,
      "name": "user1"
    },
    {
      "id": 2,
      "name": "user2"
    }
  ],
  "links": {
    "self": "link-value"
  }
}

あとがき

サンプルコードのが短く、似た様な結果になってしまい、某「全部同じじゃないですか」の様になってしまいましたが結論の所に書いた感じの使い分けで良いのかなと思いました。

今回の記事はlaravelドキュメントを見ていてサンプルコードはあるけど戻り値どうなるのか見られたら良いなと思い実際に動かしてコピペしました。
誰かの助けになれば幸いです。
(この記事はAIに壁打ちしながら作成したものとなります。)

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?