Laravelコレクション中の文字列の有無の判定方法

Laravelにて、
Eloquentでクエリビルドして（用語の使い方が不適切かも）得られたDBのコレクションの中の特定の文字列の有無をtrue/falseで返すことについて、はまってしまったので、備忘録として記す。

最終的には、コレクションをpluck('カラム名')で絞り込んでから、contains('文字列')メソッドで判定するという方法に落ち着いた。

### やりたかったこと
テーブルは、Articlesテーブル（記事テーブル）と、
お気に入り記事を格納するLikesテーブル（お気に入りテーブル）がある。

記事一覧画面において、記事ごとにお気に入りに入っているかいないかを判定したい。

判定に使うカラムは、わけあってarticle_idではなく、article_nameとしている。

### Unicodeを知らなかったため、文字化けと思ってしまった。
下のようにcontrollerでDBから値を取る。

```php:ArticleController.php

public function index(){
        $articles = Destination::paginate(20);
        $likes = Like::where('user_id', Auth::id())->get();
        return view('index', compact('articles', 'likes));
}
```
bladeファイルの中で、article->nameとlikes中のarticle_nameで同一のものがあるかの判定を記述すればいいのだが、そんななか、たまたま下のように打ったことで、ちょっと泥沼にはまった。

```php:index.blade.php
{{$likes}}
```

下のような、HTML画面になった。

```
[{"id":1,"user_id":1,"article_name":"\u30c6\u30b9\u30c8","created_at":null,"updated_at":null},
{"id":2,"user_id":1,"article_name":"\u30c6\u30b9\u30c82","created_at":null,"updated_at":null},
{"id":3,"user_id":1,"article_name":"\u30c6\u30b9\u30c83","created_at":null,"updated_at":null}]
````

なんだこれは。文字化けか？？
よくわかっていない私は、Webの検索と、意味のないトラブルシューティングを重ねた。

何時間かして、`\u30c6\u30b9\u30c8`が`テスト`のunicodeであることを理解した。

なぜ上記のようにすると日本語がUnicodeで表示されるのかはまだよくわかっていないが。。

### 意味のないトラブルシューティング例

Unicodeを理解していなかった私は、トラブルシューティングのなかで、下の意味のないものもやってしまった。

Eloquentで取得した型はコレクション。コレクションはforeachで回して値を取るというのでこれまでやってきたし、日本語もUnicodeで表示されずにきちんと表示されていた。文字化けが原因で、色々うまく行かないと思ったので、文字化けさせないことが大事と考えて、下のようにforeachを使って判定をやってみた。

```php:index.blade.php
@foreach ($articles as $article)
<tr>
       <td>{{$article->name}}</td>
<td>        
@foreach ($likes as $like)
@if ($like->article_name == $article->name)
チェック済み
@else
<div class="form-check">
    <input class="form-check-input" type="checkbox" id="{{$articles->name}}" 
      name="article_names[]" value="{{$article>name}}">
</div>
@endforeach
</td>
</tr>
@endforeach
```

結果はそう、画面がチェックボックスだらけになるという。。。。
likesテーブルのarticle_nameの値を総当りして、ほとんどがelseの方でチェックボックスを描画するという、おバカなコード。

### containsメソッドが使えない？！
コレクション中の語句が有り無しを調べればいいので、コレクションのメソッドであるcontains()を使えばいいとわかったのだが、下のようにしても、なぜか効かない。

```php:ArticleController.php
$likes = Like::where('user_id', Auth::id())->get(); //likesには'テスト'というarticle_nameが含まれている
$bool = likes->contains('テスト'); //false

//下はテスト用のコレクションを作って、contains()メソッドを試した。
$collection = collect(['テスト記事です', 'テスト記事だよ', 'テスト記事なんだね' ]);
$bool = collection->contains('テスト記事です'); //true

```

上記の`$likes`と`$collection`をdd()してみると、下のようになった。

$likesのdd結果
![スクリーンショット 2020-10-27 100308.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540509/92e7307c-22ec-3a0c-ced2-574f516609fb.png)

$collectionのdd結果
![スクリーンショット 2020-10-27 100122.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540509/41597214-83f6-f175-858f-69b09b38e19a.png)

なんだか、$likesのほうは、目的のarticle_nameまで行くには何階層もあるみたい。これが悪いのかなと思って、以下のようにしたところ、うまく行った。

### pluck()でカラムを絞り込んでから、contains()してうまくいった
```php:ArticleController.php
$like_article_names = Like::where('user_id', Auth::id())->pluck('article_name');
$bool = $like_article_names->contains('テスト');  //true
```

ようやく、'テスト'という語句がコレクション中にありますよ、と判定することができるようになった。

ということで、コレクションでcontains()を使うには、絞り込んで（？）から使う、というふうにすればいいのかなと理解した。