0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Laravel】API Resourceクラスにメタデータを追加する方法

Posted at
{
	"data": {
		//メインのデータ
	},
	"meta": {
     "key": "メタデータを表示します。"
	}
}

上記のようにResource、あるいはResourceCollectionのトップレベルにメタデータを追加する方法は、公式ドキュメント(日本語訳)メタデータの追加の項でも一応説明されているが、少し補足すると下記のようになる。

  • JsonResourceを継承したクラスでもResourceCollectionを継承したクラスのどちらでも、トップレベルの階層にメタデータを追加することができる。

  • メタデータを追加する方法として、Resourceクラスインスタンスを新しく生成する際にadditionalメソッドをチェインするか、リソースクラス内でwithメソッドをオーバーライドする2パターンがある。

  • ケースによってメタデータを含めたり含めなかったりする場合はadditionalメソッドを使用して個別にメタデータを指定し、常に共通のメタデータを使用する場合はwithメソッドを使うという使い分けで良いと思われる。

公式ドキュメントにも説明はあるが、さらっとしているのでもう少し深掘りする。

指定したデータがメタデータとして追加される仕組み

Illuminate\Http\Resources\Json\ResoureResponse
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": [
			"メタデータを表示します。",
			"メタデータを表示します。"
		]
	}
}
0
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?