laravel

[laravel] 'htmlspecialchars() expects parameter 1 to be string,~' というエラーについて

最初に

初投稿です。ものすごくピンポイントですが、結構苦しめられたのでメモとしてまとめます。laravelどころかコーディング経験も浅いので間違い等ありましたらご指摘願います。

このエラーについて

htmlspecialchars() expects parameter 1 to be string, array given

このような文章の場合、「htmlspecialchars()関数は第一引数にstring型を要求しているのに配列が渡っているぞ」というもの。laravelではviewで波括弧{{ }}を使って変数等を表示しようとしたときに現れることがある。

htmlspecialchars()とは

phpで用意されている関数の一つで、フォームから送られてきた値や、データベースから取り出した値をブラウザ上に表示する際に使用する。主に、悪意のあるコードの埋め込みを防ぐ目的で使われる。(→php-htmlspecialchars)
laravelでのblade上の波括弧{{ }}内の変数は自動的にhtmlspecialcharsに通されxss攻撃を防ぐ。5.3以前はhtmlentitiesを通す。(→laravel-blade)

解決方法

エラー自体はとても単純で、波括弧{{ }}内にhtmlspecialcharsに対応しているstring等を入れる必要がある。配列を表示したいのであれば{{$array[i]}}のように一つの要素に絞る必要がある。stringだけでなく、変数がint等の計算結果であっても問題なく表示される。コントローラーからviewへ値を渡す段階では配列等でも問題はないが、波括弧{{ }}内では一つの要素に特定する必要がある。

モデルのインスタンスは通る

今回記事にまでしてまとめようと思った原因であり、解決のきっかけにもなった。
一例として以下のような雰囲気のコードを書いた場合

controller
$users = App\User::all();
return view('index', compact('users'));
index.blade
@foreach ($users as $user)
    <p>{{$user}}</p>
    <p>{{$user->name}}</p>
    <hr>
@endforeach
{{$users}}

この場合エラーは出ない。'おそらく'モデルの機能だと思われる。

for内について、

$user->name
testUserと表示される

$user
{"user_id":1,"user_name":"testUser"}のように表示される

for外について、
$users
{"0":{"user_id":1,"user_name":"testUser"},"1":{"user_id":2,"user_name":"adminUser"}}のように表示される

明らかに複数要素あるのに問題なく表示される。詳しくlaravelのドキュメントを見れば記載されているはず。

あとがき(本題とは無関係)

エラーで迷ったらエラー文を見るのが一番。自戒です。当たり前の事なんですけど自分の場合無駄にググっちゃったりするんです...