##1. はじめに
いいね機能とは、最近のSNSにはほとんどと言ってもいいほど実装されている機能で、「好き」,「わかる」,「支持できる」などの意思表示を表すコミュニケーションツールの一種です。
いいね機能があることによって、
・(ユーザー視点)多くの投稿からどの投稿が人気もしくは信憑性があるのか。
・(投稿者視点)これまで投稿した記事でどの記事がユーザーの求めている記事なのか。
などを判断する1つの材料となります。
今回はPHPのフレームワークLaravelを使用して、いいね機能
を実装していきます。
※今回はLaravelの勉強を兼ねているため、いいね機能をサーバーサイドで処理を実装しています。本来のプロダクトであれば処理を軽くするためにもフロント側で処理を実装するかと思いますので、その点についてはご了承ください。
#####1-1. 開発環境
PHPとLaravelのバージョンは下記のグラフの通りとします。
言語・FW | バージョン |
---|---|
PHP | 7.2.26 |
Laravel | 6.17.1 |
##2. どのような仕様にするか
仕様としては1つの投稿(discussion)に複数のリプライ(Reply)が紐づくようになっていて、リプライに対していいね(Like)をつけることができます。
細かい仕様は以下のように定義します。
・初期値はいいねボタンがグレーで、いいねボタンを押すとボタンが緑色になる
・いいね数をいいねボタンの右横に表示する
・いいねボタンを2度押すといいねを取り消すことができる
・自分のリプライに対してもいいねをすることができる
・ログイン中のみに限り、リプライにいいねすることができる
##3. いいね機能の実装
それでは実際にいいね機能の実装に入っていきます。
#####3-1. ルーティング
まずはじめにいいね機能を実装する上でのルーティングを定義します。
リプライにいいねをする処理をRepliesControllerのlike()
に、
リプライに付けたいいねを解除する処理をRepliesControllerのunlike()
に記述するという定義を行います。
Route::get('/reply/like/{id}', 'RepliesController@like')->name('reply.like');
Route::get('/reply/unlike/{id}', 'RepliesController@unlike')->name('reply.unlike');
#####3-2. 情報の関係性について考える
リプライ(Reply)といいね(Like)の関係性は以下のようになります。
・1つのリプライに対して複数のいいねが紐づく
・1つのいいねに対して紐づくリプライは1つのみ
ユーザー(User)といいね(Like)の関係性は以下のようになります。
・1人のユーザーに対して複数のいいねが紐づく
・1つのいいねに対して紐づくユーザーは1人のみ
#####3-3. モデルの作成と修正
artisan
コマンドでLikeモデルとマイグレーションファイルを生成します。
$ php artisan make:model Like -m
3-2の情報の関係性
を基にしてマイグレーションファイルとモデルを修正します。
class CreateLikesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->bigIncrements('id');
$table->integer('reply_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->timestamps();
});
...
}
}
class Like extends Model
{
// 配列内の要素を書き込み可能にする
protected $fillable = ['reply_id','user_id'];
public function reply()
{
return $this->belongsTo(Reply::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
class Reply extends Model
{
...
public function likes()
{
return $this->hasMany(Like::class, 'reply_id');
}
}
#####3-4. いいね機能のビジネスロジックの実装
いいね機能のロジックを実装する上で以下の2点がポイントとなります。
・いいねボタンを押下したら、Likeテーブルに新たにレコードが生成されて、ユーザーIDとリプライIDが保存される。
・いいねしたボタンに対して、再度いいねボタンを押すと上記で生成したレコードが削除される。
上記のポイントを基に実装すると下記のようになります。
class RepliesController extends Controller
{
// only()の引数内のメソッドはログイン時のみ有効
public function __construct()
{
$this->middleware(['auth', 'verified'])->only(['like', 'unlike']);
}
...
/**
* 引数のIDに紐づくリプライにLIKEする
*
* @param $id リプライID
* @return \Illuminate\Http\RedirectResponse
*/
public function like($id)
{
Like::create([
'reply_id' => $id,
'user_id' => Auth::id(),
]);
session()->flash('success', 'You Liked the Reply.');
return redirect()->back();
}
/**
* 引数のIDに紐づくリプライにUNLIKEする
*
* @param $id リプライID
* @return \Illuminate\Http\RedirectResponse
*/
public function unlike($id)
{
$like = Like::where('reply_id', $id)->where('user_id', Auth::id())->first();
$like->delete();
session()->flash('success', 'You Unliked the Reply.');
return redirect()->back();
}
...
}
##4. いいねボタンの実装
#####4-1. いいね状態
と 非いいね状態
の表示制御
初期表示ではリプライにいいねがついておらず、いいねボタンはグレーでカウントは0、いいねをいている状態だと、いいねボタンが緑色になりカウントが1加算されます。
いいねがついているかどうかの判定を、 is_liked_by_auth_user()
内で判定して判定値をbooleanで返してあげます。
<div>
@if($reply->is_liked_by_auth_user())
<a href="{{ route('reply.unlike', ['id' => $reply->id]) }}" class="btn btn-success btn-sm">いいね<span class="badge">{{ $reply->likes->count() }}</span></a>
@else
<a href="{{ route('reply.like', ['id' => $reply->id]) }}" class="btn btn-secondary btn-sm">いいね<span class="badge">{{ $reply->likes->count() }}</span></a>
@endif
</div>
/**
* リプライにLIKEを付いているかの判定
*
* @return bool true:Likeがついてる false:Likeがついてない
*/
public function is_liked_by_auth_user()
{
$id = Auth::id();
$likers = array();
foreach($this->likes as $like) {
array_push($likers, $like->user_id);
}
if (in_array($id, $likers)) {
return true;
} else {
return false;
}
}
#####4-2. いいね数の表示
いいね数の表示は、Reply
と Like
は既にアソシエーションされているので、count()
でいいね数を取得することができます。
{{ $reply->likes->count() }}
##最後に
以上でLaravelでのいいね機能
の実装のご紹介でした!!
誤字脱字や、もっとこうした方がいいという箇所がございましたらコメント欄から教えてください!!