【Laravel】Eloquentの値返却とResourceCollectionに渡す際の工夫
eloquentからの返却値の形式がCollectionの時とModelの時で何が違うのか。
形式の違うインスタンスをそれぞれresourceCollectionで整形する為の工夫について解説します。
ModelインスタンスとCollectionインスタンス
-
Modelインスタンス
テーブルの一行を表現するオブジェクト。
eloquentで1レコードを取得する前提のメソッドの返却値はModelインスタンスになります。
find, first, create… -
Collectionインスタンス
複数のModelインスタンスを含むオブジェクト。
eloquentで複数のレコードを取得するメソッドの返却値はCollectionインスタンスになります。
all, get…
サンプルコード
all
articlesテーブルを全権取得してddで確認すると、Collectionインスタンスが返却されます。
また、artcielsテーブルは1レコードのみだったのでそれをCollectionで取得してきています。
allや後述するwhereなどの複数レコードを取得する可能性があるメソッドが、一件だけを取得してきた場合もCollectionインスタンスとして扱われるところがポイントです。
$result = Article::all();
dd($result);
whereとfind
どちらも検索のクエリを掛けるメソッドですが、下記の違いがあります。
- findで検索できるのはidのみ、whereは複数カラムで検索可能
- whereはgetで取得を行う
- findの取得は1件のみで、whereは複数権取得が可能
where
下記はwhereのサンプルです。
autoincrementのidが3なので、コードで直接3を指定してクエリを掛けています。
結果としては、Collectionインスタンスが返却されています。
$result = Article::where('id', 3)->get();
dd($return);
find
$return = Article::find(3);
dd($return);
findは1レコード前提のクエリなので、Modelインスタンスが返却されています。
ResourceCollectionへの渡し方
eloquentから取得したオブジェクトをresourceCollectionで整形してからレスポンスするケースです。
all
allではCollectionを取得できるので、resourceファイルでは$this-> でプロパティにアクセスできます
$result = Article::all();
return IndexArticleResource::collection($result);
class IndexArticleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
// response
{
"articles": [
{
"id": 3,
"title": "title01",
"content": "content01"
}
]
}
where
whereもCollecitonで返却されるので$this-> でアクセスできます。
$result = Article::where('id', 3)->get();
WhereArticleResource::collection($result);
class WhereArticleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
// response
{
"article": [
{
"id": 3,
"title": "title01",
"content": "content01"
}
]
}
find
findはModelインスタンスを返すので、ResourceCollectionに渡すにはcollectメソッドでCollection型に変換してあげる必要があります。
この場合はModelインスタンスがCollectionインスタンスに変換されるのではなく、Illuminate\Support\CollectionクラスにModelインスタンスがラップされる形でCollectionと同様の扱いをすることができるようになります。
$result= Article::find(3);
$collectResult = collect([ $result ]);
dd($collectionResult);
collectしたオブジェクトをResourceCollectionに渡してレスポンスを定義します。
$result= Article::find(3);
$collectResult = collect([ $result ]);
FindArticleResource::collection($result);
class FindArticleResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @return array<string, mixed>
*/
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
];
}
}
// response
{
"article": [
{
"id": 3,
"title": "title01",
"content": "content01"
}
]
}
ModelインスタンスはResourceCollectionに渡せませんが、collectによって渡せるようになりました。
Discussion