You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WordPress电影评分系统:未登录/已评分警告弹窗不显示求助

WordPress电影评分系统警告弹窗不显示问题排查

我在WordPress上开发了一套电影评分系统,评分功能可正常运行,但存在以下两个问题:

  • 用户未登录时,本该弹出的「请先登录再评分」警告无法显示
  • 用户已评分后,本该弹出的「你已经给这部电影评过分了」警告也无法显示
    控制台无任何报错信息,以下是相关代码,恳请帮忙排查。

rating-script.js

jQuery(document).ready(function($) {
    // Function to handle rating submission
    function handleRatingSubmission(postID, ratingValue) {
      // Check if user is logged in
      if (ratingAjax.isLoggedIn === false) {
        // User is not logged in, show error message
        $('.rating-error-message').text('Please login first before rating.').fadeIn().delay(3000).fadeOut();
        return;
      }
  
      // Send AJAX request to check if user has already rated
      $.ajax({
        url: ratingAjax.ajaxurl,
        type: 'POST',
        data: {
          action: 'check_already_rated',
          post_id: postID
        },
        success: function(response) {
          if (response.alreadyRated) {
            // User has already rated, show error message
            $('.rating-error-message').text('You have already rated this movie.').fadeIn().delay(3000).fadeOut();
          } else {
            // User has not rated, proceed with rating submission
            // Send AJAX request to update rating
            $.ajax({
              url: ratingAjax.ajaxurl,
              type: 'POST',
              data: {
                action: 'update_rating',
                post_id: postID,
                rating_value: ratingValue * 2 // Multiply the rating by 2 to convert it back to the original scale of 1-10
              },
              success: function(response) {
                if (response.success) {
                  // Rating updated successfully
                  // Display success message
                  $('.rating-success-message').fadeIn().delay(3000).fadeOut();
  
                  // Update the rating display
                  updateRatingDisplay(postID, ratingValue);
  
                  // Update the average rating display
                  var averageRating = parseFloat(response.average_rating).toFixed(2);
                  $('.rating-info[data-post-id="' + postID + '"] .average-rating').text('Average Rating: ' + averageRating);
  
                  // Update the total ratings display
                  var totalRatings = response.total_ratings;
                  $('.rating-info[data-post-id="' + postID + '"] .total-ratings').text('Total Ratings: ' + totalRatings);
                } else {
                  // Error occurred during rating update
                  // You can add additional error handling logic here
                }
              },
              error: function() {
                // Error occurred during AJAX request
                // You can add additional error handling logic here
              }
            });
          }
        },
        error: function() {
          // Error occurred during AJAX request
          // You can add additional error handling logic here
        }
      });
    }
  
    // Function to update the rating display
    function updateRatingDisplay(postID, ratingValue) {
      // Add your code here to update the rating display
      // This function should update the visual representation of the rating based on the given rating value and post ID
      // You can modify the DOM elements to reflect the updated rating
    }
  
    // Handle hover effect on rating stars
    $('.rating-stars .star').hover(function() {
      var value = $(this).data('value');
      $(this).prevAll().addBack().addClass('hover');
      $(this).nextAll().removeClass('hover');
      $(this).parent().next('.rating-hover-text').text(value);
    }, function() {
      $(this).prevAll().addBack().removeClass('hover');
      $(this).parent().next('.rating-hover-text').text('');
    });
  
    // Handle rating submission
    $('.rating-stars .star').click(function() {
      var postID = $(this).data('post-id');
      var ratingValue = $(this).data('value');
  
      // Handle rating submission for logged-in users only
      handleRatingSubmission(postID, ratingValue);
    });
  });

functions.php

<?php
// Enqueue necessary scripts and styles
function enqueue_rating_scripts() {
    wp_enqueue_script('jquery');
    wp_enqueue_script('rating-script', get_template_directory_uri() . '/js/rating-script.js', array('jquery'), false);

    // Localize the script to pass the ajaxurl value
    wp_localize_script('rating-script', 'ratingAjax', array(
        'ajaxurl' => admin_url('admin-ajax.php'),
        'isLoggedIn' => is_user_logged_in() // Add this line to pass the user login status
    ));

    wp_enqueue_style('rating-style', get_template_directory_uri() . '/css/rating-style.css');
    wp_register_style('main', get_template_directory_uri() . '/css/main.css', array(), false, 'all');
    wp_enqueue_style('main');
    wp_enqueue_style( 'google-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=Lora&family=Roboto:wght@900&display=swap', array(), null );
    wp_register_script('script', get_template_directory_uri() . '/js/script.js', array('jquery'),'1.1', true);
    wp_enqueue_script('script');
    wp_enqueue_style( 'font-awesome', 'https://use.fontawesome.com/releases/v6.1.1/css/all.css', array(), null );
}
add_action('wp_enqueue_scripts', 'enqueue_rating_scripts');


// AJAX handler to check if user has already rated
function check_already_rated() {
    if (!is_user_logged_in()) {
        wp_send_json_error(array('alreadyRated' => false)); // User is not logged in, return false
    }

    $post_id = $_POST['post_id'];
    $user_id = get_current_user_id();
    $ratings = get_field('ratings', $post_id);

    foreach ($ratings as $rating) {
        if ($rating['user_id'] == $user_id) {
            wp_send_json_error(array('alreadyRated' => true)); // User has already rated, return true
        }
    }

    wp_send_json_success(array('alreadyRated' => false)); // User has not rated, return false
}
add_action('wp_ajax_check_already_rated', 'check_already_rated');
add_action('wp_ajax_nopriv_check_already_rated', 'check_already_rated');

// AJAX handler for updating ratings
function update_rating() {
    if (!is_user_logged_in()) {
        wp_send_json_error(array('message' => 'Please login first before rating.')); // Send error response if user is not logged in
    }

    $post_id = $_POST['post_id'];
    $rating_value = $_POST['rating_value'];

    // Check if user has already rated
    $user_id = get_current_user_id();
    $ratings = get_field('ratings', $post_id);
    foreach ($ratings as $rating) {
        if ($rating['user_id'] == $user_id) {
            wp_send_json_error(array('message' => 'You have already rated this movie.')); // Send error response if user has already rated
        }
    }

    // Update ACF repeater field for the post
    $new_rating = array(
        'rating_value' => min($rating_value, 5), // Set the rating value to a maximum of 5
        'user_id' => $user_id,
        'timestamp' => current_time('Y-m-d H:i:s')
    );
    $ratings[] = $new_rating;
    update_field('ratings', $ratings, $post_id);

    // Recalculate average rating and update ACF field
    $rating_values = wp_list_pluck($ratings, 'rating_value');
    $average_rating = count($rating_values) > 0 ? round(array_sum($rating_values) / count($rating_values), 2) : null; // Round the average rating to 2 decimal places
    update_field('average_rating', $average_rating, $post_id);

    // Return success response with updated average rating and total ratings
    $response = array(
        'success' => true,
        'average_rating' => $average_rating,
        'total_ratings' => count($ratings)
    );
    wp_send_json($response);
}
add_action('wp_ajax_update_rating', 'update_rating');
add_action('wp_ajax_nopriv_update_rating', 'update_rating');

function display_rating_stars() {
    $post_id = get_the_ID();
    $rating_value = get_field('rating', $post_id);
    $ratings = get_field('ratings', $post_id);
    $average_rating = get_field('average_rating', $post_id);

    // Calculate the maximum number of stars (5)
    $max_stars = 5;

    // Calculate the number of full stars
    $full_stars = 0;
    if (is_array($ratings)) { // Check if $ratings is an array before counting
        $full_stars = min(floor($rating_value), $max_stars); // Limit the full stars to a maximum of 5
    }

    // Output the rating stars HTML
    echo '<div class="rating-stars">';
    for ($i = 1; $i <= $max_stars; $i++) {
        $star_class = ($i <= $full_stars) ? 'star active' : 'star';
        echo '<span class="' . $star_class . '" data-value="' . $i . '" data-post-id="' . $post_id . '">&#9733;</span>';
    }
    echo '</div>';

    // Output the average rating and total ratings
    echo '<div class="rating-info">';
    if (!is_null($average_rating)) {
        echo 'Average Rating: ' . number_format($average_rating, 2);
    }
    if (!is_null($ratings) && is_array($ratings)) { // Check if $ratings is an array before counting
        echo 'Total Ratings: ' . count($ratings);
    }
    echo '</div>';
}

acf-input.js

(function($) {
    acf.add_action('ready', function() {
        // Enable the ACF Number field for the rating ACF field
        $('.acf-field-number input[type="number"]').on('input', function() {
            var $input = $(this);
            var $field = $input.closest('.acf-field');
            var $label = $field.find('.acf-label');

            if ($input.val()) {
                $label.addClass('active');
            } else {
                $label.removeClass('active');
            }
        });
    });
})(jQuery);

single.php

<div class="rating-success-message" style="display: none;">
    Rating submitted successfully!
</div>
<div class="rating-error-message" style="display: none;"></div>

问题排查与修复方案

1. AJAX返回值处理错误

后端使用wp_send_json_error返回已评分状态时,前端success回调中直接读取response.alreadyRated是错误的——wp_send_json_error返回的数据会被包裹在data字段下。

  • 修复前端代码:将if (response.alreadyRated)修改为if (response.data.alreadyRated)
  • 或后端统一返回格式:改用wp_send_json替代wp_send_json_error,避免混淆回调逻辑。

2. 未登录用户的AJAX逻辑冲突

虽然前端先判断了ratingAjax.isLoggedIn,但后端check_already_rated中未登录用户会触发wp_send_json_error,导致前端进入error回调(当前为空,无任何提示)。建议:

  • 保留前端的isLoggedIn判断,确保未登录时直接显示警告,不发起AJAX请求。
  • 在前端AJAX的error回调中添加调试代码,比如:
    error: function(xhr, status, error) {
        console.log('AJAX错误:', status, error);
        console.log('响应内容:', xhr.responseText);
    }
    

3. DOM选择器范围问题

全局选择器$('.rating-error-message')可能无法精准定位当前电影的提示框,建议给提示框添加关联标识:

  • 修改single.php:
    <div class="rating-success-message" data-post-id="<?php echo get_the_ID(); ?>" style="display: none;">
        评分提交成功!
    </div>
    <div class="rating-error-message" data-post-id="<?php echo get_the_ID(); ?>" style="display: none;"></div>
    
  • 修改JS选择器:将$('.rating-error-message')改为$('.rating-error-message[data-post-id="' + postID + '"]'),确保只操作当前电影的提示框。

4. 后端ACF字段空值判断缺失

当ratings字段为空时,get_field会返回false,此时foreach循环会报错,但未被捕获。需添加数组判断:

  • 修改functions.php中的check_already_rated函数:
    function check_already_rated() {
        if (!is_user_logged_in()) {
            wp_send_json_error(array('alreadyRated' => false));
        }
    
        $post_id = $_POST['post_id'];
        $user_id = get_current_user_id();
        $ratings = get_field('ratings', $post_id);
    
        // 先判断是否为数组,避免循环报错
        if (is_array($ratings)) {
            foreach ($ratings as $rating) {
                if ($rating['user_id'] == $user_id) {
                    wp_send_json_error(array('alreadyRated' => true));
                }
            }
        }
    
        wp_send_json_success(array('alreadyRated' => false));
    }
    

5. 验证ratingAjax对象传递

在浏览器控制台执行console.log(ratingAjax),确认isLoggedIn值是否正确传递。如果未定义,检查functions.php中wp_localize_script是否绑定到正确的脚本(必须在wp_enqueue_script之后调用)。


内容的提问来源于stack exchange,提问作者payaman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:44:50