Laravelで作った募集投稿フォームのedit画面で、プルダウン(select)の項目を正しく選択してsubmitしても、必ずバリデーションエラーが出て先に進めない状態になった。
しかもcreate(新規作成)フォームは正常に動くのに、editだけ再現する。
Table of Contents
何が起きたか
エラーメッセージはこんな感じで、全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() でリクエストのキー名を直接確認する習慣が、こういうときに刺さる。