В этой статье разберем, как создать уникальную систему отзывов на сайте WordPress, где каждый отзыв будет связан с конкретным пользователем и иметь расширенные метаданные. Такая система полезна для интернет-магазинов, сервисов и любых сайтов, где важно отображать реальные отзывы с дополнительной информацией.
Создание кастомного типа записи «Отзывы»
Первым шагом создадим собственный тип записи, который позволит удобно хранить отзывы в базе. Для этого добавим в functions.php следующую функцию с префиксом wpco_:
function wpco_register_post_type_reviews() {
$labels = array(
'name' => 'Отзывы',
'singular_name' => 'Отзыв',
'add_new' => 'Добавить отзыв',
'add_new_item' => 'Добавить новый отзыв',
'edit_item' => 'Редактировать отзыв',
'new_item' => 'Новый отзыв',
'all_items' => 'Все отзывы',
'view_item' => 'Просмотр отзыва',
'search_items' => 'Поиск отзывов',
'not_found' => 'Отзывы не найдены',
'not_found_in_trash' => 'В корзине отзывов не найдено',
'menu_name' => 'Отзывы'
);
$args = array(
'labels' => $labels,
'public' => false,
'show_ui' => true,
'supports' => array('title', 'editor', 'author'),
'capability_type' => 'post',
'hierarchical' => false,
'menu_position' => 20,
'menu_icon' => 'dashicons-testimonial',
'show_in_rest' => true
);
register_post_type('wpco_review', $args);
}
add_action('init', 'wpco_register_post_type_reviews');Данный тип записи будет использоваться для хранения отзывов. Важно указать show_in_rest => true, чтобы поддерживать работу с Gutenberg и REST API.
Добавление метаполей для отзывов
Чтобы отзывы были более информативными, добавим метаполя — например, рейтинг от 1 до 5 и дату покупки. Для удобства используем плагин Clearfy Pro или сделаем вручную через add_meta_box.
function wpco_add_meta_boxes_reviews() {
add_meta_box('wpco_review_meta', 'Данные отзыва', 'wpco_review_meta_callback', 'wpco_review', 'normal', 'high');
}
add_action('add_meta_boxes', 'wpco_add_meta_boxes_reviews');
function wpco_review_meta_callback($post) {
wp_nonce_field('wpco_save_review_meta', 'wpco_review_nonce');
$rating = get_post_meta($post->ID, '_wpco_rating', true);
$purchase_date = get_post_meta($post->ID, '_wpco_purchase_date', true);
echo '<label for="wpco_rating">Рейтинг (1-5):</label> ';
echo '<input type="number" id="wpco_rating" name="wpco_rating" value="'.esc_attr($rating).'" min="1" max="5" /><br/>';
echo '<label for="wpco_purchase_date">Дата покупки:</label> ';
echo '<input type="date" id="wpco_purchase_date" name="wpco_purchase_date" value="'.esc_attr($purchase_date).'" />';
}
function wpco_save_review_meta($post_id) {
if (!isset($_POST['wpco_review_nonce']) || !wp_verify_nonce($_POST['wpco_review_nonce'], 'wpco_save_review_meta')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (isset($_POST['wpco_rating'])) {
update_post_meta($post_id, '_wpco_rating', intval($_POST['wpco_rating']));
}
if (isset($_POST['wpco_purchase_date'])) {
update_post_meta($post_id, '_wpco_purchase_date', sanitize_text_field($_POST['wpco_purchase_date']));
}
}
add_action('save_post', 'wpco_save_review_meta');Теперь у каждого отзыва можно указать рейтинг и дату покупки прямо в админке, что повышает доверие пользователей.
Привязка отзывов к зарегистрированным пользователям
Для уникальности отзывов важно, чтобы каждый пользователь мог оставить отзыв только один раз. Для этого будем использовать поле post_author у типа записи и проверять наличие отзыва при выводе формы.
Пример функции, проверяющей, оставил ли текущий пользователь отзыв:
function wpco_user_already_reviewed($user_id) {
$args = array(
'post_type' => 'wpco_review',
'author' => $user_id,
'post_status' => 'publish',
'posts_per_page' => 1
);
$query = new WP_Query($args);
return $query->have_posts();
}Перед выводом формы добавления отзыва проверяем этот вызов и выводим сообщение или форму.
Создание AJAX-формы для добавления отзыва пользователем
Чтобы упростить добавление отзывов без перезагрузки страницы, реализуем AJAX-запрос. Ниже пример реализации на jQuery и PHP.
HTML и JS для формы:
<form id="wpco-review-form">
<label>Заголовок отзыва:</label><br/>
<input type="text" name="title" required /><br/>
<label>Текст отзыва:</label><br/>
<textarea name="content" required></textarea><br/>
<label>Рейтинг (1-5):</label><br/>
<input type="number" name="rating" min="1" max="5" required /><br/>
<button type="submit">Отправить отзыв</button>
</form>
<div id="wpco-review-message"></div>
<script>
jQuery(document).ready(function($) {
$('#wpco-review-form').on('submit', function(e) {
e.preventDefault();
var data = {
action: 'wpco_add_review',
title: $(this).find('input[name=title]').val(),
content: $(this).find('textarea[name=content]').val(),
rating: $(this).find('input[name=rating]').val(),
security: wpco_ajax_object.nonce
};
$.post(wpco_ajax_object.ajax_url, data, function(response) {
$('#wpco-review-message').text(response.data.message);
if(response.success) {
$('#wpco-review-form')[0].reset();
}
});
});
});
</script>Добавим локализацию скрипта и обработчик AJAX в functions.php:
function wpco_enqueue_scripts() {
wp_enqueue_script('jquery');
wp_localize_script('jquery', 'wpco_ajax_object', array(
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wpco_add_review_nonce')
));
}
add_action('wp_enqueue_scripts', 'wpco_enqueue_scripts');
function wpco_handle_add_review() {
check_ajax_referer('wpco_add_review_nonce', 'security');
if (!is_user_logged_in()) {
wp_send_json_error(array('message' => 'Только зарегистрированные пользователи могут оставлять отзывы.'));
}
$user_id = get_current_user_id();
if (wpco_user_already_reviewed($user_id)) {
wp_send_json_error(array('message' => 'Вы уже оставили отзыв.'));
}
$title = sanitize_text_field($_POST['title']);
$content = sanitize_textarea_field($_POST['content']);
$rating = intval($_POST['rating']);
if ($rating < 1 || $rating > 5) {
wp_send_json_error(array('message' => 'Рейтинг должен быть от 1 до 5.'));
}
$post_data = array(
'post_title' => $title,
'post_content' => $content,
'post_type' => 'wpco_review',
'post_status' => 'publish',
'post_author' => $user_id
);
$post_id = wp_insert_post($post_data);
if (is_wp_error($post_id)) {
wp_send_json_error(array('message' => 'Ошибка при сохранении отзыва.'));
}
update_post_meta($post_id, '_wpco_rating', $rating);
wp_send_json_success(array('message' => 'Спасибо за ваш отзыв!'));
}
add_action('wp_ajax_wpco_add_review', 'wpco_handle_add_review');Вывод отзывов на сайте с фильтрацией по рейтингу
Для отображения отзывов сделаем WP_Query с сортировкой по рейтингу и выводом метаданных.
function wpco_show_reviews($atts) {
$atts = shortcode_atts(array(
'min_rating' => 0,
'count' => 10
), $atts);
$args = array(
'post_type' => 'wpco_review',
'posts_per_page' => intval($atts['count']),
'meta_query' => array(
array(
'key' => '_wpco_rating',
'value' => intval($atts['min_rating']),
'compare' => '>=',
'type' => 'NUMERIC'
)
),
'orderby' => 'meta_value_num',
'meta_key' => '_wpco_rating',
'order' => 'DESC'
);
$query = new WP_Query($args);
$output = '<div class="wpco-reviews">';
if ($query->have_posts()) {
while ($query->have_posts()) {
$query->the_post();
$rating = get_post_meta(get_the_ID(), '_wpco_rating', true);
$author_name = get_the_author();
$output .= '<div class="wpco-review-item">';
$output .= '<h3>'.get_the_title().'</h3>';
$output .= '<p>'.get_the_content().'</p>';
$output .= '<p>Рейтинг: ' . esc_html($rating) . ' / 5</p>';
$output .= '<p>Автор: ' . esc_html($author_name) . '</p>';
$output .= '</div>';
}
wp_reset_postdata();
} else {
$output .= '<p>Отзывов не найдено.</p>';
}
$output .= '</div>';
return $output;
}
add_shortcode('wpco_reviews', 'wpco_show_reviews');Используйте шорткод [wpco_reviews min_rating="4" count="5"] для вывода отзывов с рейтингом от 4 и более.
Рекомендации по улучшению и дополнительным плагинам
Для расширения функционала можно использовать плагин Expert Review, который добавляет удобный интерфейс для управления отзывами и рейтинговой системой. Также полезен WPRemark для отображения отзывов с красивыми шаблонами.
Важно обеспечить безопасность данных и защиту от спама, применяя nonce и проверку прав пользователей, как показано в коде.