{
"data": {
//メインのデータ
},
"meta": {
"key": "メタデータを表示します。"
}
}
上記のようにResource、あるいはResourceCollectionのトップレベルにメタデータを追加する方法は、公式ドキュメント(日本語訳)のメタデータの追加の項でも一応説明されているが、少し補足すると下記のようになる。
-
JsonResourceを継承したクラスでもResourceCollectionを継承したクラスのどちらでも、トップレベルの階層にメタデータを追加することができる。
-
メタデータを追加する方法として、Resourceクラスインスタンスを新しく生成する際にadditionalメソッドをチェインするか、リソースクラス内でwithメソッドをオーバーライドする2パターンがある。
-
ケースによってメタデータを含めたり含めなかったりする場合はadditionalメソッドを使用して個別にメタデータを指定し、常に共通のメタデータを使用する場合はwithメソッドを使うという使い分けで良いと思われる。
公式ドキュメントにも説明はあるが、さらっとしているのでもう少し深掘りする。
指定したデータがメタデータとして追加される仕組み
protected function wrap($data, $with = [], $additional = [])
{
if ($data instanceof Collection) {
$data = $data->all();
}
if ($this->haveDefaultWrapperAndDataIsUnwrapped($data)) {
$data = [$this->wrapper() => $data];
} elseif ($this->haveAdditionalInformationAndDataIsUnwrapped($data, $with, $additional)) {
$data = [($this->wrapper() ?? 'data') => $data];
}
return array_merge_recursive($data, $with, $additional);
}
$dataはレスポンスのメインとなるコレクションや配列のデータが格納される。
withメソッドで指定した配列が変数withに格納され、additionalメソッドで指定した配列が$additionalメソッドに格納されてarray_merge_recursiveによって全てマージされる。
additionalメソッドを使った場合
class HogeController extends Controller
{
public function hoge()
{
//何らかの処理
$data = ...
$value = 'メタデータを表示します。';
return (new FugaResource($data))->additional([
'meta' => [
'key' => $value,
],
]);
}
}
新しいリソースクラスのインスタンスを生成しているnew FugaResource()の箇所を丸括弧で囲み、additionalメソッドをチェインする形でメタデータを配列形式で渡す。
すると上記で渡した配列が先述した変数$additionalに格納され、最後に
array_merge_recursiveが実行されることで、レスポンスJsonに含まれるようになる。
withメソッドを使った場合
class HogeCollection extends ResourceCollection
{
public function with($request)
{
$value = 'メタデータを表示します。';
return [
'meta' => [
'key' => $value,
],
];
}
}
withメソッドで条件分岐をつけたい場合
class JsonResource implements ArrayAccess, JsonSerializable, Responsable, UrlRoutable
{
...
public $with = [];
...
public function with($request)
{
return $this->with;
}
...
}
上記のように$withの初期値は空の配列なので、APIレスポンスにメタデータを付与したくない場合は同じように空の配列を返せば良い。
class JsonResource implements ArrayAccess, JsonSerializable, Responsable, UrlRoutable
{
...
public $with = [];
...
public function with($request)
{
$value = 'meta';
if( //メタデータを返したい条件 ){
'meta' => [
'key' => $value,
],
}else{
return []; //メタデータが不要な場合は空の配列を返す。
}
}
...
}
配列の形で返さないと冒頭のarray_merge_recursiveに引っかかってエラーが発生する。
両方指定するとどうなるか
array_merge_recursiveによって結合された配列がアウトプットされる。
キーが重複する場合は上書きされるのではなく、配列に追加していく形となる。
class HogeController extends Controller
{
public function hoge()
{
//何らかの処理
$data = ...
$value = 'メタデータを表示します。';
return (new FugaResource($data))->additional([
'meta' => [
'key' => $value,
],
]);
}
}
class FugaResource extends ResourceCollection
{
public function with($request)
{
$value = 'メタデータを表示します。';
return [
'meta' => [
'key' => $value,
],
];
}
}
▼ 結果
{
"data": [],
"meta": {
"key": [
"メタデータを表示します。",
"メタデータを表示します。"
]
}
}