この記事の目的
- Bladeコンポーネントで
@propsを宣言する理由をちゃんと理解する - 宣言サボると HTMLが太る + データ漏洩 するという話
- 元ネタは @PovilasKorop さんのポスト。良い小ネタだったので布教します
そもそも何が起きるん?
こういうコンポーネントを呼び出したとします。model と class を渡してるだけのよくあるやつ。
// modelが属性としてバインドされる
<x-forms.input :model="$myModel" class="font-bold" />
問題は呼び出される側、resources/views/components/forms/input.blade.php の書き方です。
BEFORE:@propsを書いてない
// resources/views/components/forms/input.blade.php
// BEFORE: NO PROPS
<div {{ $attributes->merge(['class' => 'rounded border']) }}>
<input type="text" />
</div>
一見ちゃんと動きそうですよね。class はええ感じにマージされます。
問題はmodelの方です。
Laravelでは コンポーネント側で明示的に受け取らなかった属性は、ぜんぶ$attributesに残ったまま になります。
で、$attributes->merge() はその中身をそのままHTML属性として吐き出してしまいます。
結果のHTML(地獄)
$myModelがEloquentモデルやと、JSONにシリアライズされてこうなります👇
// RESULT HTML:
<div class="rounded border font-bold"
model="{"id":22,"client_id":19,"provider_id":14,"updated_at":"2026-05-22T06:43:45.000000Z","created_by_user_id":160}">
<input type="text" />
</div>
はい、モデルまるごとHTMLに埋め込まれてます。これがマズい理由は2つ。
注意
- HTMLが太る … モデル全体が文字列でベタ書きされるので、無駄にページが重くなる
-
データ漏洩 …
client_idやprovider_id、created_by_user_idみたいな、ユーザーに見せる必要ない内部情報がページのソースに丸見え
id だけならまだしも、内部の外部キーやら作成者IDやらがそのまま出てるの、普通にアカンやつです。
AFTER:@propsで受け取る
直し方は簡単。コンポーネントの先頭で@propsを宣言するだけ。
// resources/views/components/forms/input.blade.php
// AFTER: WITH PROPS
@props(['model'])
<div {{ $attributes->merge(['class' => 'rounded border']) }}>
<input type="text" />
</div>
@props(['model']) と書くと、model は $attributesから引っこ抜かれます。
なのでmerge()の出力にはもう含まれません。
きれいなHTML
// CLEAN HTML:
<div class="rounded border font-bold">
<input type="text" />
</div>
スッキリ🔥 漏洩もなし、無駄な肥大化もなし。
因みに、@propsで宣言した値はコンポーネント内で普通に変数として使えます。
@props(['model'])
<div {{ $attributes->merge(['class' => 'rounded border']) }}>
<input type="text" value="{{ $model->name }}" />
</div>
宣言する=「これはコンポーネントが使うデータやで」と意思表示することなので、$attributes(=そのままDOMに出る属性)と役割がきっちり分かれる、というわけです。
まとめ
- コンポーネントに渡す値は、属性かプロパティかを意識して
@propsで明示宣言する - サボると
$attributes->merge()が未宣言の値を全部HTMLに垂れ流す - 結果、HTMLが太るしモデルの中身が漏れる
- 地味やけど事故ると普通にヤバいので、コンポーネント書くときは
@props忘れないように!
以上、小ネタでした。$attributesまわり、なんとなくで書いてると足元すくわれるので気をつけましょ〜。
@ Propsについて
@props の役割は2つあります。
- 「この属性はデータ変数として扱う」という宣言。
-
@props(['model'])と書けば、渡した値をコンポーネント内で$modelとして使えます。
-
- 宣言した prop は
$attributes(属性バッグ)から引き抜かれること。- だから
$attributes->merge()してもHTMLに出てきません。 - 逆に宣言しなかった属性は
$attributesに残り、merge()でそのままDOMに出力される。
- だから
「attributeから値を取り出して変数化する」という理解でOK
