[laravel] 非同期でサクッと作るいいね機能



いいね機能自体、様式は違えど多くのサイトで見る機能ですね~
今回はAjaxを使って非同期を行っていますが、流れはこんな感じです

冒頭で紹介したサンプルをこちらにあり、Seederをつくっているので簡単に確認できるかと思います

コーディング


index.blade.php : 実際に表示する画面
like.js :いいねボタンが押されたときの処理と、実際にHTMLを書き換える処理
ProductController : jsから送られてきたデータを処理するメソッドを持つコントローラー
※authが有効になっているが前提
index.blade.php
        @if(auth()->user())
              @if(isset($product->like_products[0]))
                  <a class="toggle_wish" product_id="{{ $product->id }}" like_product="1">
                       <i class="fas fa-heart"></i>
                  </a>
              @else
                  <a class="toggle_wish" product_id="{{ $product->id }}" like_product="0">
                      <i  class="far fa-heart"></i>
                  </a> 
              @endif
          @endif  
like.js
$(function ()
{
    //「toggle_wish」というクラスを持つタグがクリックされたときに以下の処理が走る
    $('.toggle_wish').on('click', function ()
    {
        //表示しているプロダクトのIDと状態、押下し他ボタンの情報を取得
        product_id = $(this).attr("product_id");
        like_product = $(this).attr("like_product");
        click_button = $(this);

        $.ajax({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')  //基本的にはデフォルトでOK
            },
            url: '/like_product',  //route.phpで指定したコントローラーのメソッドURLを指定
            type: 'POST',   //GETかPOSTメソットを選択
            data: { 'product_id': product_id, 'like_product': like_product, }, //コントローラーに送るに名称をつけてデータを指定
                })
            //正常にコントローラーの処理が完了した場合
            .done(function (data) //コントローラーからのリターンされた値をdataとして指定
            {
                if ( data == 0 )
                {
                    //クリックしたタグのステータスを変更
                    click_button.attr("like_product", "1");
                    //クリックしたタグの子の要素を変更(表示されているハートの模様を書き換える)
                    click_button.children().attr("class", "fas fa-heart");
                }
                if ( data == 1 )
                {
                    //クリックしたタグのステータスを変更
                    click_button.attr("like_product", "0");
                    //クリックしたタグの子の要素を変更(表示されているハートの模様を書き換える)
                    click_button.children().attr("class", "far fa-heart");
                }
            })
            ////正常に処理が完了しなかった場合
            .fail(function (data)
            {
                alert('いいね処理失敗');
                alert(JSON.stringify(data));
            });
    });
});
ProductController
 public function like_product(Request $request)
    {
         if ( $request->input('like_product') == 0) {
             //ステータスが0のときはデータベースに情報を保存
             LikeProduct::create([
                 'product_id' => $request->input('product_id'),
                  'user_id' => auth()->user()->id,
             ]);
            //ステータスが1のときはデータベースに情報を削除
         } elseif ( $request->input('like_product')  == 1 ) {
             LikeProduct::where('product_id', "=", $request->input('product_id'))
                ->where('user_id', "=", auth()->user()->id)
                ->delete();
        }
         return  $request->input('like_product');
    } 

あとがき

まだまだ修行中の身なので、記事の書き方やコードについてアドバイスや編集リクエスト等があれば教えてください!