0
0

やりたいこと

Laravelで作成した記事投稿アプリなどにおいて、ユーザーが記事をいいねした際に画面遷移や更新などの同期処理ではなく非同期で反映させたい(ユーザーが一つの記事対していいねできるのは一回までにする)

Table

likesテーブルのmigration
likeがuserとarticleに紐付き、user,articleとlikesが一対多の関係

class CreateLikesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('likes', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->foreign('user_id')->references('id')->on('users')->onDelete('CASCADE');
            $table->integer('article_id')->foreign('article_id')->references('id')->on('articles')->onDelete('CASCADE');
            $table->timestamps();
            $table->timestamp('deleted_at')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('likes');
    }
}

Model

articleとlikeのリレーションなど

Article.php
class Article extends Model
{
    //Likeとのリレーション
    public function likes()
    {
        return $this->hasMany(Like::class);
    }
    //いいねされてるかの判定
    public function isLiked(){
        $like = Like::where('user_id', Auth::id())->where('article_id', $this->id)->first();
        if($like !== null){
            return true;
        }
        return false;
    }
}
User.php
class User extends Authenticatable
{
    use Notifiable;

    //Articleとのリレーション
    public function articles(){
        return $this->hasMany(Article::class);
    }

    //Likeとのリレーション
    public function likes(){
        return $this->hasMany(Like::class);
    }
}
Like.php
class Like extends Model
{
    protected $fillable = [
        'user_id', 'article_id'
    ];
    //Userとのリレーション
    public function user(){
        return $this->belongsTo(User::class);
    }
    //Articleとのリレーション
    public function article(){
        return $this->belongsTo(Article::class);
    }
}

Route

web.php
Route::post('/article/like/{id}', 'LikesController@like')->name('like');

Controller

簡潔にするためcontrollerに更新などのロジックも書いています

public function like(Request $request){
    $article_id = $request->article_id;
    $article = Article::findOrFail($article_id);
    // 実行ユーザーがいいね済みかどうかの確認
    if($article->isLiked()){
        // いいね済みであれば解除
        $article->likes()->where('user_id',Auth::id())->delete();
    } else {
        // 未いいねであれば登録
        $article->likes()->create(['user_id' => Auth::id()]);
    }
    $likes_count = $article->likes()->count();
    $params = [ 'likes_count' => $likes_count ];
    //カウント後のいいね数をjsonで返却
    return response()->json($params);
}

記事画面

detail.blade.php
記事に紐づくいいね数を表示

<span class="likes">
  <i class="bi bi-hand-thumbs-up like-toggle" article_id="{{ $article->id }}"></i>
  <span class="like-counter">{{$article->likes->count()}}</span>
</span>

Ajax

public/js/like/like.js
$(function () {
    let like = $('.like-toggle'); //like-toggleのついたiタグを取得し代入。
    let article_id;
    like.on('click', function () {
      let $this = $(this); //this=イベントの発火した要素=iタグを代入
      article_id = $this.data('article_id'); //iタグに仕込んだdata-review-idの値を取得
      //ajax処理スタート
      $.ajax({
        headers: {
          'X-CSRF-TOKEN' : $('meta[name="csrf-token"]').attr('content')
        },
        url: '/article/like',
        method: 'POST',
        data: {
          'article_id': article_id //いいねされた投稿のidを送る
        },
      })
      //成功した時の処理
      .done(function (data) {
        // 返却されたカウント後のいいね数を表示
        $this.next('.like-counter').html(data.likes_count);
      })
      //失敗した時の処理
      .fail(function () {
        console.log('err');
      });
    });
});
0
0
0

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
0
0