Debug My Life.

いろいろデバッグをがんばるブログ。

Laravelとinputのname属性の配列使用時のold値指定のエラーでハマった件

久しぶりによく分からないエラーにハマったので、備忘録的に示しておこう。

LaravelのView(bladeファイル)でinputを使用して、以下のような配列を受け渡すHTMLを作っていた。

<input type="text" name="price-0[]" value="100" class="align-right" style="width:100px;"><input type="text" name="price-0[]" value="200" class="align-right" style="width:100px;"><input type="text" name="price-1[]" value="300" class="align-right" style="width:100px;"><input type="text" name="price-1[]" value="400" class="align-right" style="width:100px;"><input type="text" name="price-2[]" value="500" class="align-right" style="width:100px;"><input type="text" name="price-2[]" value="600" class="align-right" style="width:100px;">

name属性のprice-0は、POST受け渡し時にrequest値で配列として取得できる。そんで、これを列方向にも連番だけ違うname属性を増やして行列の2次元配列で渡すことを想定していた(上記HTMLはイメージなので不完全な構成)。

上記のHTMLを出力するためにinputを以下のように定義していた(変数$i, $jはそれぞれ行と列のループ処理用で、ループ処理記述は省略)。

<input type="text" name="price-{{$j}}[]" value="{{ old("price-".$j", $rateValues[$i][$j]) }}" class="align-right" style="width:100px;"> 円

そんで保存処理で以下のようなエラーになってしまった。

[2017-10-29 09:55:28] local.ERROR: htmlspecialchars() expects parameter 1 to be string, array given (View: /var/www/mice/laravel/resources/views/venue/reservation/configuration/room/form.blade.php) {"userId":1,"email":"test@test.jp","exception":"[object] (ErrorException(code: 0): htmlspecialchars() expects parameter 1 to be string, array given (View: /var/www/mice/laravel/resources/views/venue/reservation/configuration/room/form.blade.php) at /var/www/mice/laravel/vendor/laravel/framework/src/Illuminate/Support/helpers.php:577, ErrorException(code: 0): htmlspecialchars() expects parameter 1 to be string, array given at /var/www/mice/laravel/vendor/laravel/framework/src/Illuminate/Support/helpers.php:577)

htmlspecialchars()のエラーはあまり見ないので、最初はController側かと思ったけど、エラーメッセージはblade側を示している。htmlspecialchars()はblade内で変数出力するために使う{{ }}のところで内部的の呼び出されているらしいので、{{ }}を使っているところを見ても、エラーメッセージの示すstringが指定されるべきところに配列が渡っているところが分からず、結局怪しそうなところ(今回はold値を使用しているところ)を一つずつコメントアウトして、上記のinput部分であることは突き止められた。

結局以下のようにold値の最初の引数に1次元配列が渡っていたのが原因なので、そこをしっかり配列の中身の要素を渡すようにして解決した。

<input type="text" name="price-{{$j}}[]" value="{{ old("price-".$j.".".$i, $rateValues[$i][$j]) }}" class="align-right" style="width:100px;">

name属性を2次元配列($jのようにname属性の連番で列方向を示し、各name自身は実質1次元配列)で渡す場合、old値の受け渡しもちゃんと price-".$j.".".$i で渡すのを見落としていて、4時間くらいハマってしまった(ビール飲んでからやってたので若干酔っていたというのもあるが)・・・。

ちなみに、name属性の配列の要素をold値で取得するには name名.要素番号 で指定できる。