Hiroyukiです。
本日は、PHP/Laravelを使って、
####いいね!機能・いいね!ボタンを実装する方法!
について解説して行きます!
Twitterの影響か、みんな作ってみたい機能ですよね〜
完成イメージは下記の通りでーす!
####「いいね!を付ける」ボタンを押すと、「いいね!を外す」ボタンに切り替わって、
####右上に「いいね!の取得数」が表示される感じですねー!!
#どういう方針で作るの?
さて、今回は前提として、下記の画像のような
####ユーザ:コンテンツで、「1対多」の関係
があるようなサービスが既に作られている前提で、話を進めて行きま〜す!
つまり、今回の「いいね!」機能では、各ユーザが各ムービー(コンテンツ)に「いいね!」をする形ですね。
いいね!機能の実装といっても、いろいろな方法があるとは思いますが
####ユーザとコンテンツの間に、いいね!機能を持たせる「中間テーブル」を作成する方法で解説したいと思います。
僕が作っているのが、下記サイトの、動画を使ったSNSサービスみたいなものなので、
コンテンツは 「movies(動画)」 となっていますが、
####ツイッタークローンなど作成の場合も、実装方法は全く同じだと思いますので、
####是非ぜひ参考にしてみてくださーい^^
※Twitterクローンの場合は、
コンテンツが「つぶやき(tweets,micropostsなど)」に変わるだけですね!
####ボクのオリジナルサービス 【いいね!機能実装済み】
####●YouTubeまとめ × コミュニケーション
####http://youtubematome.herokuapp.com
#いいね!テーブルの作成
では早速作って行きまっしょ〜
テーブルの名前は何でもOKですが、「favorites」テーブルとかで、いいでしょう!
$ php artisan make:migration create_favorites_table --create=favorites
で、生成されるのが、下記の通りのデータです!
migrations/年月日時_create_favorites_table.php の up() と down()
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->index();
$table->integer('movie_id')->unsigned()->index();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('movie_id')->references('id')->on('movies')->onDelete('cascade');
$table->unique(['user_id','movie_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('favorites');
}
}
マイグレーションを実行します。
$ php artisan migrate
#モデルに追記していく
中間テーブルのための「Model」などは作らずに進めて行きますが
その代わりに、Userモデル等を少しイジらないといけません!
User.php(抜粋)
public function favorites()
{
return $this->belongsToMany(Movie::class, 'favorites', 'user_id', 'movie_id')->withTimestamps();
}
public function favorite($movieId)
{
$exist = $this->is_favorite($movieId);
if($exist){
return false;
}else{
$this->favorites()->attach($movieId);
return true;
}
}
public function unfavorite($movieId)
{
$exist = $this->is_favorite($movieId);
if($exist){
$this->favorites()->detach($movieId);
return true;
}else{
return false;
}
}
public function is_favorite($movieId)
{
return $this->favorites()->where('movie_id',$movieId)->exists();
}
####favorites()関数 → Userクラスが、favoritesテーブルを通して、Movieクラスと繋がっている
####(それぞれのidで関連づけられている)
ということを表しています。
更に
####is_favorite()関数 → 既に「いいね!」しているか?
を判定するための関数も追記していますっ!
そして、
####favorite()関数 → 「いいね!」を付ける!
####unfavorite()関数 → 「いいね!」を外す!
という、それぞれの処理が行われるというやり方ですな。
そしてそして、、、
####「いいね!」の数を表示させたい人は、コンテンツのモデル(ボクの場合はMovieモデル)もイジりませう〜
コンテンツのモデルMovie.php(抜粋)に以下を追記する
public function favorite_users()
{
return $this->belongsToMany(User::class,'favorites','movie_id','user_id')->withTimestamps();
}
これで、コンテンツに「いいね!」しているユーザーをサクッと抜き出すことができます!!
カンタンですね〜^^
#ルーティング
web.php
Route::group(['middleware'=>'auth'],function(){
Route::group(['prefix'=>'movies/{id}'],function(){
Route::post('favorite','FavoriteController@store')->name('favorites.favorite');
Route::delete('unfavorite','FavoriteController@destroy')->name('favorites.unfavorite');
});
});
該当するidを持っているmovieに対して、favorite(いいね!付ける)/unfavorite(いいね!外す)の処理がされるように
ルーティングを設定するわけです。
#コントローラーを実装
まず、いいね!専用コントローラーを作っちゃいましょ〜
$ php artisan make:controller FavoriteController
んで、生成できたら、その中身を追記します。
FavoriteController.php の store と destroy
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class FavoriteController extends Controller
{
public function store(Request $request, $id)
{
\Auth::user()->favorite($id);
return back();
}
public function destroy($id)
{
\Auth::user()->unfavorite($id);
return back();
}
}
#いいね!ボタンの実装
いよいよ完成が近づいてきましたね〜
viewの任意の位置に、「いいね!」ボタンを作成しましょ!
view
@if (Auth::id() != $user->id)
@if (Auth::user()->is_favorite($movie->id))
{!! Form::open(['route' => ['favorites.unfavorite', $movie->id], 'method' => 'delete']) !!}
{!! Form::submit('いいね!を外す', ['class' => "button btn btn-warning"]) !!}
{!! Form::close() !!}
@else
{!! Form::open(['route' => ['favorites.favorite', $movie->id]]) !!}
{!! Form::submit('いいね!を付ける', ['class' => "button btn btn-success"]) !!}
{!! Form::close() !!}
@endif
@endif
解説:
下記の判定後、それぞれのボタンを表示しています。
####・自分が閲覧しているユーザが自分自身ではないか?
####・自分が既にこのコンテンツを「いいね!」しているかどうか?
つまり、判定を要約すると、
####閲覧しているユーザが自分自身でなく、かつ、既に「いいね!」済みの時 → 「いいね!を外す」ボタンを表示
####閲覧しているユーザが自分自身でなく、かつ、まだ「いいね!」済みではない時 → 「いいね!を付ける」ボタンを表示
が、それぞれ表示されます!!
これが上手く実装できて表示された時は、かなり嬉しいですね〜
####初学者のボクは跳び上がって喜びました(笑)
#いいね!取得数の表示
いいね!の数を表示たい方は、実装方法を見ていきませう〜
ここで、さっきMovie(皆さんのコンテンツの)モデルに
####favorite_users()
を書き込んだのが効いてきます。
いいね!の数を表示させるviewに情報を渡すコントローラーに、下記を追記します。
対象のコントローラー
class UsersController extends Controller
{
public function index()
{
$count_favorite_users = $movie->favorite_users()->count();
$data=[
'count_favorite_users'=>$count_favorite_users,
];
return view('いいね!の数を表示させるview名',$data
);
}
では最後!
いいね!数の表示部分の実装ですー
viewに追記
<div class="text-right mb-2">いいね!
<span class="badge badge-pill badge-success">{{ $count_favorite_users }}</span>
</div>
#実装後どんな感じになるの?
####はい、完成です!
今一度、完成後の様子を見たい方は、
いいね!機能実装済みのサイトを公開してますので、是非下記からご覧下さいね〜
####ボクのオリジナルサービス 【いいね!機能実装済み】
####●YouTubeまとめ × コミュニケーション
####http://youtubematome.herokuapp.com
#次回は・・・
今回は、いいね!機能と、各コンテンツの「いいね!」数の表示のみでしたが、
####次回は、ユーザが「いいね!」をゲットした総数(各コンテンツの「いいね!」数をトータルした合計数)
を表示させる方法を解説したいと思っています(これがまたまた苦労しました、、、汗)
ではまた、Hiroyukiでした!!!