Tạo hệ thống đánh giá (rating) an toàn và nhẹ cho WordPress bằng code

Bạn muốn cho phép người dùng đánh giá bài viết trên website mà không dùng plugin nặng nề? Trong bài viết này, mình sẽ hướng dẫn cách tạo hệ thống đánh giá đơn giản nhưng đủ an toàn – có kiểm tra IP, nonce, giới hạn điểm, và phản hồi AJAX mượt mà.

Tạo hệ thống đánh giá (rating) an toàn và nhẹ cho WordPress bằng code

Nếu bạn không muốn sử dung plugin, ví dụ Tạo mục đánh giá bài viết đơn giản với KK Star Ratings, thì có thể tham khảo bài viết này.

1. Tạo bảng đánh giá (tuỳ chọn – nếu muốn lưu riêng)

CREATE TABLE wp_post_ratings (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  post_id BIGINT UNSIGNED NOT NULL,
  rating TINYINT UNSIGNED NOT NULL,
  ip_address VARCHAR(45),
  rated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  UNIQUE KEY unique_rating (post_id, ip_address)
) DEFAULT CHARSET=utf8mb4;

Nếu không cần lưu chi tiết, bạn có thể bỏ qua và dùng post_meta như bước dưới.

2. Giao diện đánh giá

<div id="rating-box" data-post-id="<?php the_ID(); ?>">
  <span data-rating="1">★</span>
  <span data-rating="2">★</span>
  <span data-rating="3">★</span>
  <span data-rating="4">★</span>
  <span data-rating="5">★</span>
</div>
<div id="rating-message"></div>

3. JavaScript AJAX gửi điểm đánh giá

document.querySelectorAll('#rating-box span').forEach(star => {
  star.addEventListener('click', () => {
    const rating = star.dataset.rating;
    const postID = document.getElementById('rating-box').dataset.postId;

    fetch(myRating.ajax_url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: `action=save_post_rating&rating=${rating}&post_id=${postID}&nonce=${myRating.nonce}`
    })
    .then(res => res.json())
    .then(data => {
      document.getElementById('rating-message').textContent = data.message;
    });
  });
});

Đừng quên enqueue và localize script:

function enqueue_rating_assets() {
    wp_enqueue_script('rating-script', get_template_directory_uri() . '/rating.js', [], false, true);
    wp_localize_script('rating-script', 'myRating', [
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('rate_nonce')
    ]);
}
add_action('wp_enqueue_scripts', 'enqueue_rating_assets');

4. Xử lý AJAX trong PHP

function save_post_rating() {
    if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'rate_nonce')) {
        wp_send_json_error(['message' => 'Lỗi bảo mật.']);
    }

    $post_id = absint($_POST['post_id']);
    $rating = absint($_POST['rating']);
    $ip = $_SERVER['REMOTE_ADDR'];

    if ($rating < 1 || $rating > 5) {
        wp_send_json_error(['message' => 'Điểm không hợp lệ.']);
    }

    // Kiểm tra xem IP đã đánh giá chưa
    $rated_ips = get_post_meta($post_id, '_rated_ips', true);
    $rated_ips = is_array($rated_ips) ? $rated_ips : [];

    if (in_array($ip, $rated_ips)) {
        wp_send_json_error(['message' => 'Bạn đã đánh giá bài này.']);
    }

    // Cập nhật điểm trung bình
    $total = (int) get_post_meta($post_id, '_rating_total', true);
    $count = (int) get_post_meta($post_id, '_rating_count', true);

    update_post_meta($post_id, '_rating_total', $total + $rating);
    update_post_meta($post_id, '_rating_count', $count + 1);

    // Ghi IP lại
    $rated_ips[] = $ip;
    update_post_meta($post_id, '_rated_ips', $rated_ips);

    wp_send_json_success(['message' => 'Cảm ơn bạn đã đánh giá!']);
}
add_action('wp_ajax_save_post_rating', 'save_post_rating');
add_action('wp_ajax_nopriv_save_post_rating', 'save_post_rating');

5. Hiển thị điểm trung bình

$total = (int) get_post_meta(get_the_ID(), '_rating_total', true);
$count = (int) get_post_meta(get_the_ID(), '_rating_count', true);

if ($count > 0) {
    $average = round($total / $count, 1);
    echo '<div>Đánh giá trung bình: ' . $average . '/5 (' . $count . ' lượt)</div>';
}

Tổng kết

  • Bạn đã có một hệ thống đánh giá bài viết cơ bản nhưng đủ an toàn
  • Có thể nâng cấp lưu vào database riêng để phân tích sâu hơn
  • Giao diện có thể dễ dàng tùy biến theo UIkit, Tailwind, Bootstrap…

Nếu muốn mở rộng, bạn có thể thêm đánh giá có nội dung, thống kê theo ngày, hoặc kết hợp với Google Rich Snippets để hiển thị kết quả trên SERP!

Bình luận


  • Không có bình luận.

Init Toolbox

Nhấn Ctrl + \ trên máy tính, hoặc vuốt sang trái ở bất kỳ đâu trên mobile.

Đăng nhập





Đang tải...