Laravel いいね機能の実装part1
完成形
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行ずつ解説していきます
- $likesは最終的にbladeに渡す変数です。配列の形で渡します。
- 今回のオリジナルポイントです。詳しくは後ほど説明しますが、$likes配列の1つ目にdummy(ダミー)を代入
- $outfitsには表示される投稿などの全データが入っていれば大丈夫です。
- これから表示される投稿それぞれに該当する「likes」テーブルのレコードを取得し、$likeへ代入
- $likeがあれば、いいねしている→ピンクのハート。なければ、いいねをしていない->グレーのハート。1か0で分岐させる
- 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を使用しました。
詳しい使い方は下記サイトを参照してください以上です。part2に続く