Laravelで、いいねした写真の一覧を表示するには
写真素材:
pixabay.com
上のようないいねをした画像を取得して、表示する部分について解説します。
取りたい情報
・写真がいいねされた数
・写真のコメントの数
3つのテーブルを用意
まず、3つのテーブルを使用します。
ユーザーテーブル、写真テーブル、いいねテーブル
カラムは必要なところだけをかくと
●ユーザーテーブル
・id (これが他のテーブルと紐づくuser_id)
・他、nameなどのカラム
●写真テーブル
・id (これが他のテーブルと紐づくphoto_id)
・user_id
・他、titleなどのカラム
●いいねテーブル
・user_id (これが他のテーブルと紐づくuser_id)
・photo_id
※user_idとphoto_idは組み合わせが重複しないように複合キーにする。
マイグレーションファイル一部
<?php ... Schema::create('skill_user', function (Blueprint $table) { $table->unsignedInteger('skill_id'); $table->unsignedInteger('user_id'); $table->primary(['skill_id', 'user_id']);//複合キー ...
SQLからデータを取得
例えば、ユーザー1が、いいねをした写真一覧を取得するということなので、
内部結合で表すと
INNAR JOIN SELECT photos.id FROM photos INNER JOIN favorites ON photos.id = favorites.photo_id and favorites.user_id = $user_id;
Laravelでは
<?php $photos = DB::table('photos') ->join('favorites', 'photos.id', '=', 'favorites.photo_id') ->where('favorites.user_id', '=', $user_id) ->get(); return view('mypage')->with([ 'photos' => $photos, ... ]);
となりますが、
これだと、viewの方で、photosをforeachで回したとき、
子要素のphotoでリレーションを使う時にエラーが出ました。
まぁ…配列のデータしか取れてないことが原因なわけですが…
hasManyThroughを使おう
よってそのため、以下のように【hasManyThrough】を使って、3つのテーブルをまたぐリレーションを行います。
<?php ... class User extends Authenticatable{ //~省略~ public function join_favorites_photos() { return $this->hasManyThrough( 'App\Photo', //リレーションして取りたいテーブル「photos」 'App\Favorite', //経由するテーブル「favorites」 'user_id', //favoritesテーブルをusersテーブルと結ぶための外部キー 'id', // photosテーブルの外部キー null, // usersテーブルのローカルキー 'photo_id' //favoritesとphotosを結ぶために使うキー ); } }
リレーション先テーブル「posts」
rolesテーブルのidとmembersテーブルのroles_idを結合
membersテーブルのidとPostsテーブルのmembers_idを結合
bladeでいいねの数とコメントの数を表示する部分を作成
これをすると、2つのテーブルで行うhasManyなどのリレーションと同じように
子要素のリレーションもビューでデータを取得できます。
実際に、いいねの数と、コメントの数をビューで表示してみましょう。
<?php // いいねの数 $photo->favorites->count(); // コメントの数 $photo->comments->count();
ビューの部分
<div class="gallery flex border mb-4 p-2"> @foreach ($photos as $photo) <div class="photo border mb-4 p-2"> <a href="/photo/{{ $photo->id }}"> <div class="img_cover"> <img src="/storage/thumbnail_images/{{ $photo->image_name }}" /> </div> </a> <div class="flex space-between bottom-imginfo"> <div> <img src="/img/heart-regular.svg" width="20"> <u><b>{{ $photo->favorites->count() }}</b></u> ←ここでしっかりデータが取得できる <img src="/img/comment-dots-regular.svg" width="20"> <u><b>{{ $photo->comments->count() }}</b></u> ←ここでしっかりデータが取得できる </div> <div> <form method="POST" action="{{ action('FavoriteController@destroy_redirect', ['photo_id' => $photo->id]) }}"> @csrf @if ($page_kind === 'mypage') <button type="button" class="btn btn-primary btn-sm">編集</button> @endif <button type="submit" class="btn btn-danger btn-sm"> @if ($page_kind === 'favorite') 解除 @else 削除 @endif </button> </form> </div> </div> </div> @endforeach </div>
これで完成です。
参考サイト
qiita.com