APIレスポンスJSONの標準形式であるJSON:APIをサポートした新しいリソース
次に紹介するのは、EloquentのAPIリソースに新しく追加されたJSON:APIリソースです。
APIリソースとその作り方
LaravelでWeb APIを作成しようとすると、Eloquentのモデル内のプロパティのデータを加工してJSONデータとし、それをレスポンスとすることが多々あります。場合によっては、プロパティのデータそのものを、ほぼ加工なしにJSONデータとすることもあります。
こういった処理を簡単に実装できる仕組みとして、LaravelにはAPIリソースがあります。
たとえば、カクテル情報を管理するモデルとしてCocktailがあるとして、このモデルを利用してJSONデータを生成したい場合、リスト1のクラスを作成します。
<?php
:
class CocktailResource extends JsonResource // (1)
{
public function toArray(Request $request): array // (2)
{
return [
"id" => $this->id,
:
];
}
}
こういったクラスをリソースクラスと言い、app/Http/Resources/フォルダー内に「モデル名+Resource」クラス名で作成します。
そして、リスト1の(1)のように、JsonResourceクラスを継承して作成します。その上で(2)のtoArray()メソッドを作成します。このメソッドの戻り値として、JSONデータとする配列を定義します。この配列は、モデルクラスに保持したデータベースの1件分のデータを加工して作成します。その際、モデルが保持したデータは、$this->でアクセスできます。
なお、こういったクラスのスケルトンコードを自動生成してくれるartisanコマンドも用意されています。次のコマンドです。
php artisan make:resource リソースクラス名
リソースクラスの使い方
こうしたクラスを作成しておくと、あとはコントローラクラスでリスト2のコードを記述するだけです。
<?php
:
class CocktailController extends Controller
{
public function index()
{
return Cocktail::all()->toResourceCollection(); // (1)
}
public function show(Cocktail $cocktail)
{
return $cocktail->toResource(); // (2)
}
}
リスト2の(1)のように、モデルクラスのメソッドを利用して取得したリストデータに対して、toResourceCollection()メソッドを実行し、その結果をリターンするだけです。これだけで、リソースクラスを利用したJSONデータを生成し、リスト3の通りJSONデータがレスポンスとして返ってきます。
{
"data": [
{
"id": 1,
"name": "…",
:
},
:
]
}
もし、1件だけのJSONデータを取得するAPIとしたい場合は、コントローラクラスではリスト2の(2)のように、モデルオブジェクトに対してtoResource()メソッドを実行し、その結果をリターンするだけです。
JSON:APIとは
ここまで紹介したAPIリソース機能は、これまでも存在したものです。これに、バージョン13で新たに追加されたのがJSON:APIリソースです。
リスト3を見てもわかるように、通常のリソースクラスを利用した場合、レスポンスとなるJSONデータの各オブジェクト構造は、モデルのプロパティを加工したものが列挙されているだけです。リスト1のtoArray()メソッドの処理がそのようになっているため当然です。
一方、最近のWeb APIには、JSON:APIが登場しています。これは、Web APIのレスポンスJSONデータの形式を統一しようというものであり公式Webサイトに詳細が記載されています。
その概略を記載すると、リスト4のJSONデータ構造となります。dataプロパティの配列オブジェクトにおいて、idプロパティとtypeプロパティが必須として設定されており、各データは、attributesプロパティオブジェクト内に列挙する形となっています。
{
"data": [
{
"id": IDの値
"type": リソースの種類
"attributes": {
カラムの値,
:
}
},
:
]
}
JSON:APIリソースの作り方
このJSON:API形式に従ったJSONデータをレスポンスとするための仕組みが、バージョン13で導入されました。そういったリソースのコントローラでの使い方は、通常のリソースと同じです。
一方、作り方は異なります。クラスを作成する場合のコマンドは、次のように--json-apiオプションをつけます。
php artisan make:resource リソースクラス名 --json-api
たとえば、リスト1のCocktailResourceをJSON:APIリソースとして作成すると、リスト5のコードとなります。
<?php
:
class CocktailJsonApiResource extends JsonApiResource // (1)
{
public $attributes = [ // (2)
"name",
:
];
public $relationships = [ // (3)
];
public function toType(Request $request): string // (4)
{
return "cocktails";
}
}
まず、リスト5の(1)のように、JsonApiResourceを継承して作成します。その上で、クラス内には(2)のように、$attributesプロパティを、カラム名の配列として定義します。ここに定義したカラム名(モデルのプロパティ名)のデータが、そのままレスポンスJSONデータのattributesプロパティオブジェクト内に列挙されます。
その際に、カラムデータの加工が必要な場合は、$attributesプロパティの代わりに、次のtoAttributes()メソッドを定義します。メソッド内のコードは、通常のリソースクラスのtoArray()メソッドと同じです。
public function toAttributes(Request $request): array
{
return [
"name" => $this->name,
:
];
}
さらに、リレーション先を指定したい場合は(3)のように、$relationshipsプロパティに配列としてリレーション先テーブル名を列挙します。
同様に(4)のように、toType()メソッドも定義できます。こちらは、その戻り値がレスポンスJSONデータのtypeプロパティの値として利用されます。もしこのメソッドが定義されていない場合は、リソースクラス名からResourceを取り除いた文字列をスネーク記法に変更し、最後を複数形にした文字列がtypeプロパティの値として利用されます。たとえば、CocktailJsonApiResourceクラスの場合は、cocktail_json_apisとなります。
また、リスト5にはありませんが、toId()メソッドを定義することで、データベース上のidの値とは別の値を、レスポンスJSONデータのidプロパティの値として指定できるようになります。
