Laravel いいね機能の実装part1

4 min読了の目安(約3600字TECH技術記事

完成形

PHPとLaravelだけで実装します(javascript,vue.jsは使いません)
作成にあたり、いくつかの記事を参考にしましたが、より簡単に実装できるように工夫しました

いいねボタン


             ↓ハートをクリックするとピンク色に(もう一度押すと戻る)

いいねの回数表示(いいねボタンとは別)

いいねボタン

migrate

いいねの状況をデータとして管理する「likes」テーブルを作成

いいねをつけたユーザーのidといいねがついた投稿のidをカラムとして作成

Schema::create('likes', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->integer('user_id');
            $table->integer('outfit_id');
            $table->timestamps();
        });

Like.phpも作っておく

class Like extends Model
{
    //テーブル名
    protected $table = 'likes';

    //userとのリレーション
    public function user()
    {
        return $this->belongTo('App\User');
    }

    //outfitとのリレーション
    public function outfit()
    {
        return $this->belongTo('App\Outfit');
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'user_id','outfit_id'
    ];

    protected $guarded = [
        'id'
    ];
}

route

//いいねをつける
Route::get('/home/like/{id}','HomeController@exeOther_outfitLike')->name('like_home');

//いいねを消す
Route::get('/home/nolike/{id}','HomeController@exeOther_outfitNolike')->name('nolike_home')

{id}で送られるのは「いいね」の対象となる投稿のidです

Controller

/**
* いいねをつける
* @param $id outfitのid
* @return view
*/
public function exeOther_outfitLike($id)
{
	$like=new Like;
	$like->user_id=Auth::id();
	$like->outfit_id=$id;
	$like->save();

	return redirect(route('home'));
}
/**
* いいねを消す
* @param $id outfitのid
* @return view
*/
public function exeOther_outfitNolike($id)
{
	$user_id=Auth::id();
	$like=Like::where('user_id',$user_id)->where('outfit_id',$id)->first();
	$like->delete();

	return redirect(route('home'));
}

$user_idとoutfit_idが一致するレコードがある
→すでにいいねが押されている
→それを削除することでいいね状態を解除

次にいいねの状態をどうやって反映させるかです
ここが一番苦戦しました

//いいねの取得
$likes=array();
$likes[0]='dummy';
foreach($outfits as $outfit)
{
	$like=Like::where('user_id',$id)->where('outfit_id',$outfit['id'])->first();
	if(!empty($like))
	{
		$like=1;
	}else
	{
		$like=0;
	}
	array_push($likes,$like);
}

上から1行ずつ解説していきます

  1. $likesは最終的にbladeに渡す変数です。配列の形で渡します。
  2. 今回のオリジナルポイントです。詳しくは後ほど説明しますが、$likes配列の1つ目にdummy(ダミー)を代入
  3. $outfitsには表示される投稿などの全データが入っていれば大丈夫です。
  4. これから表示される投稿それぞれに該当する「likes」テーブルのレコードを取得し、$likeへ代入
  5. $likeがあれば、いいねしている→ピンクのハート。なければ、いいねをしていない->グレーのハート。1か0で分岐させる
  6. array_push(データが挿入される配列,挿入されるデータ)

以上より、$likesには投稿が表示される順に従って、0か1の数字が格納されている

Blade

これらの外で投稿を表示するためのforeachが書かれている必要がある。今回の場合だと

@foreach($outfits as $outfit)
...........
	<div class="d-inline float-right">
	    @if($likes[$loop->iteration]==1)
		<a href="{{route('nolike_home',$outfit->id)}}"><i class="fas fa-heart fa-2x my-pink"></i></a>
	    @else
		<a href="{{route('like_home',$outfit->id)}}"><i class="fas fa-heart fa-2x my-gray"></i></a>
	    @endif
	</div>
...........
@endforeach

route(ルート名,$hoge->id)と第二引数に指定したものがrouteの{id}に送られます

$loop->iteration


公式リファレンスの説明がこちら

1回目のforeachの処理では1つ目の投稿の表示が行われる
→$likes[1]が1つ目の投稿がいいねの状況なので、
→$likes[0]はいらない情報となる。しかし、配列は0から始まるので、ダミーのデータを挿入
→これにより、$loop->iterationの数値を表示される投稿の順番の番号が等しくなり、それぞれの投稿にいいねの状況が表示される。

ハートとiタグ

Font Awesomeを使用しました。
https://fontawesome.com/
詳しい使い方は下記サイトを参照してください
https://saruwakakun.com/html-css/basic/font-awesome

以上です。part2に続く