Отзывы с рейтингом в WordPress без плагинов: пошаговое создание

В этой статье разберёмся, как реализовать функционал отзывов с рейтингом в WordPress без использования плагинов. Многие сайты нуждаются в удобной системе отзывов с возможностью выставлять оценки, но не хотят нагружать сайт лишними расширениями. Мы создадим простую, но гибкую систему на базе собственных типов записей, метаполей и пользовательских шаблонов, а также добавим Ajax-отправку отзывов и валидацию данных.

Создание пользовательского типа записей для отзывов

Для начала нам нужно зарегистрировать кастомный тип записи — wpcom_review. Это позволит хранить отзывы отдельно от стандартных постов и удобно управлять ими в админке.

function wpcom_register_review_post_type() {
    $labels = array(
        'name' => 'Отзывы',
        'singular_name' => 'Отзыв',
        'add_new' => 'Добавить отзыв',
        'add_new_item' => 'Добавить новый отзыв',
        'edit_item' => 'Редактировать отзыв',
        'new_item' => 'Новый отзыв',
        'view_item' => 'Просмотреть отзыв',
        'search_items' => 'Поиск отзывов',
        'not_found' => 'Отзывы не найдены',
        'not_found_in_trash' => 'В корзине отзывов не найдено',
        'menu_name' => 'Отзывы'
    );
    $args = array(
        'labels' => $labels,
        'public' => true,
        'has_archive' => false,
        'menu_position' => 20,
        'supports' => array('title', 'editor', 'author'),
        'capability_type' => 'post',
        'show_in_rest' => true
    );
    register_post_type('wpcom_review', $args);
}
add_action('init', 'wpcom_register_review_post_type');

Этот код добавьте в файл functions.php вашей темы или в отдельный плагин. Теперь в админке появится раздел "Отзывы".

Добавление рейтинга — метаполе для отзывов

Для рейтинга будем использовать метаполе, в котором хранится число от 1 до 5. Добавим это поле в админку с помощью метабокса.

function wpcom_add_rating_meta_box() {
    add_meta_box(
        'wpcom_rating_meta_box',
        'Рейтинг отзыва',
        'wpcom_render_rating_meta_box',
        'wpcom_review',
        'side',
        'default'
    );
}
add_action('add_meta_boxes', 'wpcom_add_rating_meta_box');

function wpcom_render_rating_meta_box($post) {
    wp_nonce_field('wpcom_save_rating_meta_box', 'wpcom_rating_meta_box_nonce');
    $rating = get_post_meta($post->ID, '_wpcom_review_rating', true);
    ?>
    <label for="wpcom_review_rating">Выберите рейтинг (1-5):</label>
    <select name="wpcom_review_rating" id="wpcom_review_rating">
        <option value="">--Выберите--</option>
        <?php for ($i = 1; $i <= 5; $i++): ?>
            <option value="<?php echo $i; ?>" <?php selected($rating, $i); ?>><?php echo $i; ?></option>
        <?php endfor; ?>
    </select>
    <?php
}

function wpcom_save_rating_meta_box($post_id) {
    if (!isset($_POST['wpcom_rating_meta_box_nonce']) || !wp_verify_nonce($_POST['wpcom_rating_meta_box_nonce'], 'wpcom_save_rating_meta_box')) {
        return;
    }
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }
    if (isset($_POST['wpcom_review_rating'])) {
        $rating = intval($_POST['wpcom_review_rating']);
        if ($rating >= 1 && $rating <= 5) {
            update_post_meta($post_id, '_wpcom_review_rating', $rating);
        } else {
            delete_post_meta($post_id, '_wpcom_review_rating');
        }
    }
}
add_action('save_post', 'wpcom_save_rating_meta_box');

Теперь при создании или редактировании отзыва можно указать рейтинг от 1 до 5 звезд.

Вывод отзывов с рейтингом на сайте

Реализуем шаблон для вывода списка отзывов с рейтингом. В шаблоне темы (например, в page-reviews.php или в кастомном шаблоне) можно использовать WP_Query:

$args = array(
    'post_type' => 'wpcom_review',
    'posts_per_page' => 10,
    'post_status' => 'publish'
);
$review_query = new WP_Query($args);

if ($review_query->have_posts()) :
    echo '<div class="wpcom-reviews-list">';
    while ($review_query->have_posts()) : $review_query->the_post();
        $rating = get_post_meta(get_the_ID(), '_wpcom_review_rating', true);
        echo '<div class="wpcom-review-item">';
        echo '<h3>' . get_the_title() . '</h3>';
        echo '<div class="wpcom-review-rating">' . wpcom_render_stars($rating) . '</div>';
        echo '<div class="wpcom-review-content">' . get_the_content() . '</div>';
        echo '</div>';
    endwhile;
    echo '</div>';
    wp_reset_postdata();
else :
    echo '<p>Отзывов пока нет.</p>';
endif;

function wpcom_render_stars($rating) {
    $output = '';
    for ($i = 1; $i <= 5; $i++) {
        if ($i <= $rating) {
            $output .= '<span style="color:#f5a623;">★</span>'; // заполненная звезда
        } else {
            $output .= '<span style="color:#ccc;">★</span>'; // пустая звезда
        }
    }
    return $output;
}

Этот код выведет отзывы с визуальным отображением рейтинга в виде звезд.

Форма добавления отзывов с рейтингом с поддержкой Ajax

Для удобства пользователей создадим форму отправки отзыва с полем для рейтинга и реализуем обработку через Ajax. Это позволит отправлять отзывы без перезагрузки страницы.

HTML форма

<form id="wpcom-review-form" method="post">
    <label for="wpcom-review-title">Заголовок отзыва:</label>
    <input type="text" id="wpcom-review-title" name="title" required />

    <label for="wpcom-review-content">Текст отзыва:</label>
    <textarea id="wpcom-review-content" name="content" required></textarea>

    <label for="wpcom-review-rating">Рейтинг:</label>
    <select id="wpcom-review-rating" name="rating" required>
        <option value="">--Выберите--</option>
        <option value="1">1</option>
        <option value="2">2</option>
        <option value="3">3</option>
        <option value="4">4</option>
        <option value="5">5</option>
    </select>

    <input type="submit" value="Отправить отзыв" />
    <div id="wpcom-review-message"></div>
</form>

JavaScript для Ajax

jQuery(document).ready(function($) {
    $('#wpcom-review-form').on('submit', function(e) {
        e.preventDefault();
        var data = {
            action: 'wpcom_submit_review',
            title: $('#wpcom-review-title').val(),
            content: $('#wpcom-review-content').val(),
            rating: $('#wpcom-review-rating').val(),
            nonce: wpcom_ajax_object.nonce
        };
        $.post(wpcom_ajax_object.ajax_url, data, function(response) {
            $('#wpcom-review-message').html(response.data.message);
            if(response.success) {
                $('#wpcom-review-form')[0].reset();
            }
        });
    });
});

Регистрация скрипта и локализация данных

function wpcom_enqueue_scripts() {
    wp_enqueue_script('jquery');
    wp_enqueue_script('wpcom-review-script', get_template_directory_uri() . '/js/wpcom-review.js', array('jquery'), null, true);
    wp_localize_script('wpcom-review-script', 'wpcom_ajax_object', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('wpcom_review_nonce')
    ));
}
add_action('wp_enqueue_scripts', 'wpcom_enqueue_scripts');

Обработка Ajax-запроса на сервере

function wpcom_handle_review_submission() {
    check_ajax_referer('wpcom_review_nonce', 'nonce');

    $title = sanitize_text_field($_POST['title']);
    $content = sanitize_textarea_field($_POST['content']);
    $rating = intval($_POST['rating']);

    if (empty($title) || empty($content) || $rating < 1 || $rating > 5) {
        wp_send_json_error(array('message' => 'Пожалуйста, заполните все поля корректно.'));
    }

    $review_post = array(
        'post_title' => $title,
        'post_content' => $content,
        'post_status' => 'pending', // можно менять на 'publish' после модерации
        'post_type' => 'wpcom_review'
    );

    $post_id = wp_insert_post($review_post);

    if (is_wp_error($post_id)) {
        wp_send_json_error(array('message' => 'Ошибка при сохранении отзыва. Попробуйте позже.'));
    }

    update_post_meta($post_id, '_wpcom_review_rating', $rating);

    wp_send_json_success(array('message' => 'Спасибо за ваш отзыв! Он появится после проверки.'));
}
add_action('wp_ajax_wpcom_submit_review', 'wpcom_handle_review_submission');
add_action('wp_ajax_nopriv_wpcom_submit_review', 'wpcom_handle_review_submission');

Дополнительные советы и улучшения

1. Чтобы улучшить визуальное отображение рейтинга, можно подключить иконки SVG или шрифты с иконками (например, FontAwesome) вместо символов ★.

2. Для управления отзывами можно использовать плагины, например, Expert Review от WPSHOP, который расширит функционал и добавит фильтры и модерацию.

3. Для защиты от спама добавьте капчу или дополнительные проверки на сервере.

4. Можно расширить метаданные отзывы, добавив имя автора, email, дату посещения и т.д.

5. Для вывода среднего рейтинга по всем отзывам используйте функцию агрегации метаданных через WP_Query с аргументом meta_query и meta_key.

Сервис определения шаблона и плагинов на сайте