Laravelコレクション中の文字列の有無の判定方法
Laravelにて、
Eloquentでクエリビルドして(用語の使い方が不適切かも)得られたDBのコレクションの中の特定の文字列の有無をtrue/falseで返すことについて、はまってしまったので、備忘録として記す。
最終的には、コレクションをpluck('カラム名')で絞り込んでから、contains('文字列')メソッドで判定するという方法に落ち着いた。
やりたかったこと
テーブルは、Articlesテーブル(記事テーブル)と、
お気に入り記事を格納するLikesテーブル(お気に入りテーブル)がある。
記事一覧画面において、記事ごとにお気に入りに入っているかいないかを判定したい。
判定に使うカラムは、わけあってarticle_idではなく、article_nameとしている。
Unicodeを知らなかったため、文字化けと思ってしまった。
下のようにcontrollerでDBから値を取る。
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で同一のものがあるかの判定を記述すればいいのだが、そんななか、たまたま下のように打ったことで、ちょっと泥沼にはまった。
{{$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を使って判定をやってみた。
@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()を使えばいいとわかったのだが、下のようにしても、なぜか効かない。
$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のほうは、目的のarticle_nameまで行くには何階層もあるみたい。これが悪いのかなと思って、以下のようにしたところ、うまく行った。
pluck()でカラムを絞り込んでから、contains()してうまくいった
$like_article_names = Like::where('user_id', Auth::id())->pluck('article_name');
$bool = $like_article_names->contains('テスト'); //true
ようやく、'テスト'という語句がコレクション中にありますよ、と判定することができるようになった。
ということで、コレクションでcontains()を使うには、絞り込んで(?)から使う、というふうにすればいいのかなと理解した。
Author And Source
この問題について(Laravelコレクション中の文字列の有無の判定方法), 我々は、より多くの情報をここで見つけました https://qiita.com/kohboh/items/ab76128864640b6863cd著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .