Laravelのeditフォームだけselectのバリデーションエラーになる原因と解決方法

2026.07.03

Laravelで作った募集投稿フォームのedit画面で、プルダウン(select)の項目を正しく選択してsubmitしても、必ずバリデーションエラーが出て先に進めない状態になった。

しかもcreate(新規作成)フォームは正常に動くのに、editだけ再現する。

何が起きたか

エラーメッセージはこんな感じで、全selectに対してまとめて出る。

性別 は必ず指定してください
年齢 は必ず指定してください
健康状態 は必ず指定してください
(以下、select項目すべて)

「選んでるのになぜ?」という状態で、最初はJavaScript側かFormRequestのルール設定を疑った。

試したこと(全部ハズレだった)

1. PostRequest.php のバリデーションルールを確認 → 問題なし
2. dd($request->all()) でリクエスト内容をダンプ → ここで異変に気づく

ダンプ結果を見ると、フィールド名がおかしかった。

array:20 [
  "\u201dcategory_id\u201d" => "1"
  "\u201dgender\u201d" => "オス"
  ...
]

フィールド名に \u201d が混入している。

\u201d はUnicodeの「RIGHT DOUBLE QUOTATION MARK(右二重引用符)」、つまり " というカーリークォートだ。バリデーション側は category_id を期待しているのに、ブラウザは "category_id" という名前でデータを送ってくる。当然バリデーションは通らない。

原因

resources/views/components/forms/select.blade.php のHTMLソースを xxd コマンドでバイト単位に確認したところ、HTML属性の区切り文字にASCIIのダブルクォート(U+0022)ではなく、カーリークォート(U+201D)が使われていた。

{{-- 問題のあった状態(見た目はほぼ同じだが別の文字)--}}
<select name="category_id" ...>
            ↑
     実はここが "(U+201D)で囲まれていた

HTMLパーサーはカーリークォートを属性の終端と認識しないため、"category_id" という文字列ごとフィールド名として送信してしまっていた。エディタ上では肉眼で判別不能で、コピペや補完の際に誤ったコードポイントが混入したと思われる。

解決方法

select.blade.php のカーリークォートをASCIIのダブルクォートに一括置換する。Pythonでバイト直接置換するのが確実だ。

with open('select.blade.php', 'rb') as f:
    content = f.read()
content = content.replace(b'\xe2\x80\x9d', b'"')
with open('select.blade.php', 'wb') as f:
    f.write(content)

\xe2\x80\x9d はU+201DのUTF-8バイト表現だ。テキストエディタの「置換」は見た目が同じ文字として認識できない場合があるため、バイナリレベルで置換するのがポイントになる。

置換後にBladeのキャッシュをクリアして完了。

php artisan view:clear

まとめ

1. 症状:editフォームのselectだけバリデーションエラー、createは正常
2. 原因:Bladeテンプレートの属性区切りに "(U+201D)が混入し、フィールド名が "foo" として送信される
3. 発見:dd($request->all()) でキー名に \u201d を確認
4. 解決:Pythonでバイト単位に \xe2\x80\x9d" へ置換 + キャッシュクリア

肉眼では絶対に気づけないし、エラーメッセージからも原因が全くわからないタイプのバグだった。

dd() でリクエストのキー名を直接確認する習慣が、こういうときに刺さる。

PIC UP