📘

【Laravel × Vue】「データが無限にネストされる」現象とその解決法

に公開

どんな現象?

とあるプロジェクトで

案件テーブル:projects
 ├── 原価計算表:estimates
 ├── 現場管理表:progress_reports

という構成のデータをLaravel bladeからvueコンポーネントへ渡すさいに開発メンバーから共有された現象についてです。

LaravelでAPIやVue.js用にデータを返すとき、
「project → estimate 」という親子関係でデータを渡すように設定したつもりが

"project": {
	"id": 268,
	"company_id": 1,
	"name": "案件名",
	"status": 1,
	"created_at": "2025-08-27T19:26:42.000000Z",
	"estimate": {
		"id": 240,
		"company_id": 1,
		"project_id": 268,
		"estimate_cost": 260000,
		"created_at": "2025-10-27T14:34:32.000000Z",
		"project": {
			"id": 268,
			"company_id": 1,
			"name": "案件名",
			"status": 1,
			"created_at": "2025-08-27T19:26:42.000000Z",
		}
	},
}

「project → estimate → project → estimate ...」

のように
同じデータが何重にも入れ子(ネスト)になってしまい、ループ状態に、、
レスポンスがとても大きくなったり、フロントでエラーになってしまっていた。。。


何が起きていたの?

  • 「親子リレーションが双方向」:
    • Laravelの「リレーション」という機能で、
      たとえば「Project(案件)」と「Estimate(見積)」を
      お互いに参照できるようにしていました(親子関係が双方向)。
  • 「子で親を参照するアクセサ」:
    • さらに「Estimate」モデルの中で、
      「親のProjectの値を使って計算する」アクセサ(getXxxAttribute)を作っていました。
  • 「APIでJSON返却」
    • その状態で、APIでデータを返すときに
      Project::with('estimate')->get() のようにリレーションごと取得し、
      そのまま response()->json($projects) で返していました。
「親子リレーションが双方向」+「子で親を参照するアクセサ」+「APIでJSON返却」

というこの3つの特定の条件が重なった場合のみ発生していた様子。。


どこでハマった?

  • Bladeで @dd($projects[0]->estimate) などで中身を見ても
    普通のデータ構造に見えるので、
    なぜAPIレスポンスやVueのpropsで
    「project → estimate → project → ...」と
    無限にネストされるのか分かりませんでした。

なぜ無限ループになるの?

  1. ProjectのestimateリレーションをAPIで返す
  2. Estimateの「計算用アクセサ」が親のProjectを参照する
  3. そのProjectのestimateリレーションをまたAPIで返す…
  4. これがずっと繰り返されてしまう

どうやって解決するの?

Estimateモデルに下記を1行追加するだけ!

[Estimate.php]
protected $hidden = ['project'];

これで「APIやtoJson/toArrayでデータを返すときだけ」
estimateの中のprojectリレーションが除外され、
無限ループが防げます。
コード内やBlade、アクセサでは普通に $this->project で親にアクセスできます。

まとめ

この3つが揃うと、データが無限にネストされることがある
protected $hidden = ['除外したいリレーション名']; を使えば解決できます!
「APIのレスポンスがやたら大きい」「Vueでpropsが変」などで困ったら、
まずはこのパターンを疑ってみてください!

備考

chatgptによると
Laravel公式でも推奨されている一般的な解決策とのことですが、一応他にも解決策はあるそうで他の選択肢として「APIリソース(Resourceクラス)で明示的に出力項目を制御する」という方法もあるようす。
現場によって判断すべきなのかなぁと。。。!

Discussion