サポート » 使い方全般 » 自作いいね機能について

  • 解決済 non888

    (@non888)


    各投稿へのいいね機能をAJAXを用いて自作しております。
    いろいろと調べながら機能を実装し下記コードで動作はしているのですが、私があまり深いところまでプログラミングに精通しておらず、現在学習中のためこちらのコードで問題がないか・もっと改善できる点はないかと不安に思っております。
    もしよろしければ、コードの改善点や現状のコードだと発生する問題点などご教授いただけませんでしょうか。
    よろしくお願いいたします。

    ■仕様
    ・カスタム投稿など含む各投稿の一覧や詳細ページにいいねボタンを表示させる
    ・各ユーザーはログイン、未ログイン関係なくいいねボタンの「On」「Off」が可能
    ・ユーザーがある投稿にいいねを行い、再度サイトに訪れた際に、一定の期間はいいね状態の情報を保持し、該当の投稿では、いいね(On)の状態で表示させる
    ・いいねした情報は各ユーザーごとに保持させる
    例えば、ユーザーAはいいねしたがユーザーBはいいねしていない場合、ユーザーAのみいいね状態とする

    ■コード_サイト表示用ショートコードいいねボタン

    /** いいねボタン表示 **/
    function view_good_btn()
    {
        global $post;
        $postID = $post->ID;
        $count = get_field('good_counter', $postID);
    
        if(empty($good_count) && $good_count != 0){ //カスタムフィールド「いいね数」が空の場合0をセット
            update_post_meta( $postID, 'good_counter', 0, $count );
            $good_count = get_field('good_counter', $postID);
        }
    
        if(isset($_COOKIE['post_'.$postID])){ //すでにその投稿のいいねをしているか確認
            //いいねしていたらOn状態のボタン表示
            $output = '<button class="good_button good_in_button" data-id="'. $postID .'">';
            $output .= '<span class="good_counter">'. $count .'</span>';
            $output .= '</button>';
        } else {
            //いいねしていなければOff状態のボタン表示
            $output = '<button class="good_button good_not_button" data-id="'. $postID .'">';
            $output .= '<span class="good_counter">'. $count .'</span>';
            $output .= '</button>';
        }
    
      return $output;
    }
    add_shortcode('good_btn', 'view_good_btn');

    ■コード_Ajax(いいねボタンクリック時)

    <script>
    $(document).on('click','.good_button',function(){
      var $target = $(this);
      var count_num = Number($target.find('.good_counter').html());
      if($target.hasClass('good_in_button')){
        var count = count_num - 1;
        $target.removeClass('good_in_button');
        $target.addClass('good_not_button');
      } else {
        var count = count_num + 1;
        $target.removeClass('good_not_button');
        $target.addClass('good_in_button');
      }
    
      jQuery.ajax({
        url: '<?=admin_url('admin-ajax.php')?>',
        type: 'POST',
        data: {
          'action' : 'count_up',
          'postID' : $target.data('id')
        },
        success: function(data) {
            $target.find('.good_counter').html(count);
        }
      });
      return false;
    });
    </script>

    ■コード_いいねカウント処理

    function count_up(){
      $postID = $_POST['postID']; //投稿ID
      $count = get_field('good_counter',$postID);
    
      if(isset($_COOKIE['post_'.$postID])){ //すでにその投稿のいいねをしているか確認
    
        if($count > 0){
            //すでにいいねしており該当の投稿のいいね数が0より大きければ-1する
            update_post_meta( $postID, 'good_counter', $count - 1, $count );
        }
        setcookie('post_'.$postID, $postID, time() - 30, '/', $_SERVER['HTTP_HOST']); // Cookieから該当の投稿情報を削除
      } else {
        setcookie('post_'.$postID, $postID, time() + 60 * 60 * 24 * 30, '/', $_SERVER['HTTP_HOST']); //いいねした投稿情報をCookieに保存
        update_post_meta( $postID, 'good_counter', $count + 1, $count ); //まだいいねしていなければいいね数を+1
      }
    
      die();
    }
    add_action( 'wp_ajax_count_up', 'count_up' );
    add_action( 'wp_ajax_nopriv_count_up', 'count_up' );

    ■やっていること
    各投稿のいいね数は、ACFを用いてカスタムフィールドを作成し、そちらに保存しております。
    いいねした情報をユーザーごとに保持させるためいいねを行った投稿IDをCookieに保存し、管理を行っております。
    投稿IDのみをキーとすると、他システムとの競合があるのではと思い、「post_」という文字列を付けております。

    「サイト表示用ショートコードいいねボタン」にて、いいねと紐づける投稿IDでCookieに情報があれば、「On」状態のClass「good_in_button」をつけたボタンを表示、それ以外の場合は「Off」状態のClass「good_not_button」を付けたボタンを表示させております。

    いいねボタンをクリックした際にAjaxにて、「コード_いいねカウント処理」に対してカウント処理を行っております。
    また、DB側のカウントの数字は「+1」もしくは「-1」されたものになっておりますが、フロント画面ではリロードしないと反映されない状態のため、jQueryにてカウントの変動を行っております。

    「コード_いいねカウント処理」では、投稿IDをもとにすでにCookieがあるのであれば、カウントを「-1」してCookieから該当の投稿ID情報を削除しています。
    Cookieがなければ、投稿IDをもとにCookieを保存し、カウントを「+1」させております。

3件の返信を表示中 - 1 - 3件目 (全3件中)
  • スレッド開始 non888

    (@non888)

    掲載しているコードに誤字があったのと、Cookieの保存できる数に上限があることがわかり、配列で情報を持たせることとしました。

    ■コード_サイト表示用ショートコードいいねボタン

    function view_good_btn()
    {
        global $post;
        $postID = $post->ID;
        $count = get_field('good_counter', $postID);
    
        if(empty($count) && $count != 0){ //カスタムフィールド「いいね数」が空の場合0をセット
            update_post_meta( $postID, 'good_counter', 0, $count );
            $count = get_field('good_counter', $postID);
        }
    
        if(isset($_COOKIE['good']) && array_key_exists($postID, $_COOKIE['good'])){
            //いいねしていたらOn状態のボタン表示
            $output = '<button class="good_button good_in_button" data-id="'. $postID .'">';
            $output .= '<span class="good_counter">'. $count .'</span>';
            $output .= '</button>';
        } else {
            //いいねしていなければOff状態のボタン表示
            $output = '<button class="good_button good_not_button" data-id="'. $postID .'">';
            $output .= '<span class="good_counter">'. $count .'</span>';
            $output .= '</button>';
        }
    
      return $output;
    }
    add_shortcode('good_btn', 'view_good_btn');

    ■コード_いいねカウント処理

    function count_up(){
      $postID = $_POST['postID']; //投稿ID
      $count = get_field('good_counter',$postID);
    
      if(isset($_COOKIE['good']) && array_key_exists($postID, $_COOKIE['good'])){ //すでにその投稿のいいねをしているか確認
    
        if($count > 0){
            //すでにいいねしており該当の投稿のいいね数が0より大きければ-1する
            update_post_meta( $postID, 'good_counter', $count - 1, $count );
        }
        setcookie('good['.$postID.']', $postID, time() - 30, '/', $_SERVER['HTTP_HOST']); // Cookieから該当の投稿情報を削除
      } else {
        setcookie('good['.$postID.']', $postID, time() + 60 * 60 * 24 * 30, '/', $_SERVER['HTTP_HOST']); //いいねした投稿情報をCookieに保存
        update_post_meta( $postID, 'good_counter', $count + 1, $count ); //まだいいねしていなければいいね数を+1
      }
    
      die();
    }
    add_action( 'wp_ajax_count_up', 'count_up' );
    add_action( 'wp_ajax_nopriv_count_up', 'count_up' );
    • この返信は2ヶ月前にnon888が編集しました。

    @non888さん

    こんにちは。

    概ね問題ないコードかと思いますが、品質・セキュリティ向上のためのポイントをいくつかお伝えします。
    ※動作確認していないためエラーがあるかもしれず調整も必要かもしれません

    ■コード_サイト表示用ショートコードいいねボタン

    function view_good_btn()
    {
    
        // ACFプラグインが無効化されている(get_field等が使えない)場合は何もしない
        if(!function_exists('get_field')) return;
    
        global $post;
        $postID = $post->ID;
        $count = get_field('good_counter', $postID);
    
        if(!$count){ //ACFのget_fieldはレコ―ドがなければ確かfalseを返すので、このようにシンプルに書ける
            //値の取得をACFのget_fieldでやるなら、値の更新も以下のようにACFの関数で統一するべき
            update_field('good_counter', 0, $postID);
            $count = get_field('good_counter', $postID);
        }
    
        // いいねしたかどうかの状態からボタン用クラスを作成(三項演算子)
        $button_class = isset($_COOKIE['good']) && array_key_exists($postID, $_COOKIE['good']) ? 'good_in_button' : 'good_not_button';
    
        // button_classを作っておけば、一行でシンプルに書ける
        // 変数を埋め込む時は無害化する(esc_attr、esc_html)
        // buttonにはちゃんとtype属性を付ける
        // 中にspanタグを入れなくてもよい
        $output = '<button type="button" class="good_button ' . esc_attr($button_class) . '" data-id="'. $postID .'">' . esc_html($count) . '</button>';
    
        return $output;
    }
    add_shortcode('good_btn', 'view_good_btn');

    ■コード_Ajax(いいねボタンクリック時)

    <script>
    $(document).on('click','.good_button',function(){
      var $target = $(this);
      // 先に二つのクラスをremoveしておく
        $target.removeClass('good_in_button good_not_button');
    
      if($target.hasClass('good_in_button')){
        //レスポンスデータからカウントを取得するため不要
        // var count = count_num - 1;
        $target.addClass('good_not_button');
      } else {
        //レスポンスデータからカウントを取得するため不要
        // var count = count_num + 1;
        $target.addClass('good_in_button');
      }
    
      jQuery.ajax({
        url: ajaxurl, // グローバル変数を使う(後述)
        type: 'POST',
        data: {
          'action' : 'count_up',
          'postID' : $target.data('id')
        },
        success: function(res) {
            レスポンスデータからカウント数を設置
            $target.text(res);
        }
      });
    
      // 不要
      // return false;
    });
    </script>

    備考:Ajax用のURLをJavaScriptグローバル変数として出力しておく

    function add_my_ajaxurl() {
    ?>
        <script>
            var ajaxurl = '<?php echo admin_url( 'admin-ajax.php'); ?>';
        </script>
    <?php
    }
    add_action( 'wp_head', 'add_my_ajaxurl', 1 );

    ■コード_いいねカウント処理

    function count_up(){
      // postIDが渡ってこなかった時の事も考慮すべき
      if(!isset($_POST['postID'])) die();
    
      // ACFプラグインが無効化されている(get_field等が使えない)場合は何もしない
      if(!function_exists('get_field')) return;
    
      $postID = $_POST['postID']; //投稿ID
      $count = get_field('good_counter',$postID);
    
      if(isset($_COOKIE['good']) && array_key_exists($postID, $_COOKIE['good'])){ //すでにその投稿のいいねをしているか確認
    
        if($count > 0){
            //すでにいいねしており該当の投稿のいいね数が0より大きければ-1する
    
            //値の取得をACFのget_fieldでやるなら、値の更新も以下のようにACFの関数で統一するべき
            update_field('good_counter', $count - 1, $postID);
        }
        setcookie('good['.$postID.']', $postID, time() - 30, '/', $_SERVER['HTTP_HOST']); // Cookieから該当の投稿情報を削除
      } else {
        setcookie('good['.$postID.']', $postID, time() + 60 * 60 * 24 * 30, '/', $_SERVER['HTTP_HOST']); //いいねした投稿情報をCookieに保存
    
        //値の取得をACFのget_fieldでやるなら、値の更新も以下のようにACFの関数で統一するべき
        update_field('good_counter', $count + 1, $postID);
      }
    
      //新しいカウント数を返却する
      the_field('good_counter',$postID);
      die();
    }
    add_action( 'wp_ajax_count_up', 'count_up' );
    add_action( 'wp_ajax_nopriv_count_up', 'count_up' );
    スレッド開始 non888

    (@non888)

    @wildworks
    ご連絡ありがとうございます。
    また、改善ポイントにつきまして、ありがとうございます。
    いただきましたコードを参考に調整をしてみます。

    • この返信は2ヶ月前にnon888が編集しました。
3件の返信を表示中 - 1 - 3件目 (全3件中)
  • このトピックに返信するにはログインが必要です。