LoginSignup
0
2

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-10-27

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

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

やりたかったこと

テーブルは、Articlesテーブル(記事テーブル)と、
お気に入り記事を格納するLikesテーブル(お気に入りテーブル)がある。

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

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

Unicodeを知らなかったため、文字化けと思ってしまった。

下のようにcontrollerでDBから値を取る。

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で同一のものがあるかの判定を記述すればいいのだが、そんななか、たまたま下のように打ったことで、ちょっと泥沼にはまった。

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を使って判定をやってみた。

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()を使えばいいとわかったのだが、下のようにしても、なぜか効かない。

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

$collectionのdd結果
スクリーンショット 2020-10-27 100122.png

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

pluck()でカラムを絞り込んでから、contains()してうまくいった

ArticleController.php
$like_article_names = Like::where('user_id', Auth::id())->pluck('article_name');
$bool = $like_article_names->contains('テスト');  //true

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

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

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2