LoginSignup
31
37

More than 3 years have passed since last update.

「いいね!機能の実装方法」詳しく解説〜PHP/Laravelを使って

Last updated at Posted at 2019-09-22

Hiroyukiです。

本日は、PHP/Laravelを使って、

いいね!機能・いいね!ボタンを実装する方法!

について解説して行きます!

Twitterの影響か、みんな作ってみたい機能ですよね〜

完成イメージは下記の通りでーす!

「いいね!を付ける」ボタンを押すと、「いいね!を外す」ボタンに切り替わって、

右上に「いいね!の取得数」が表示される感じですねー!!

スクリーンショット 2019-09-22 9.45.55.png

どういう方針で作るの?

さて、今回は前提として、下記の画像のような

ユーザ:コンテンツで、「1対多」の関係

があるようなサービスが既に作られている前提で、話を進めて行きま〜す!

スクリーンショット 2019-09-22 8.04.11.png

つまり、今回の「いいね!」機能では、各ユーザが各ムービー(コンテンツ)に「いいね!」をする形ですね。
いいね!機能の実装といっても、いろいろな方法があるとは思いますが

ユーザとコンテンツの間に、いいね!機能を持たせる「中間テーブル」を作成する方法で解説したいと思います。

僕が作っているのが、下記サイトの、動画を使った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

スクリーンショット 2019-09-17 8.05.39.png

次回は・・・

今回は、いいね!機能と、各コンテンツの「いいね!」数の表示のみでしたが、

次回は、ユーザが「いいね!」をゲットした総数(各コンテンツの「いいね!」数をトータルした合計数)

を表示させる方法を解説したいと思っています(これがまたまた苦労しました、、、汗)

ではまた、Hiroyukiでした!!!

31
37
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
37