Для многих сайтов на WordPress важно иметь функциональную и надежную систему отзывов, которая позволяет пользователям оставлять комментарии, а администратору — подтверждать и модерировать эти отзывы. В этой статье мы подробно разберём, как создать собственную систему отзывов с подтверждением, используя кастомный тип записи, мета-поля и AJAX для удобства пользователей.
Почему стоит делать собственную систему отзывов в WordPress
Стандартные комментарии WordPress подходят для базовых нужд, но часто не обладают необходимой гибкостью и возможностями, такими как:
- Подтверждение отзывов администратором перед публикацией
- Добавление рейтинга (звёздочек) к отзыву
- Вывод отзывов в определённых частях сайта с фильтрацией
- Улучшенная защита от спама
Создавая собственную систему, вы получаете полный контроль над функционалом и дизайном, а также возможность расширять систему под конкретные задачи.
Создание кастомного типа записи для отзывов
Первый шаг — зарегистрировать новый тип записи «Отзывы». Это позволит отделить отзывы от стандартных постов и страниц, а также использовать все преимущества WordPress для работы с ними.
function wpall_register_reviews_cpt() {
$labels = array(
'name' => 'Отзывы',
'singular_name' => 'Отзыв',
'add_new' => 'Добавить отзыв',
'add_new_item' => 'Добавить новый отзыв',
'edit_item' => 'Редактировать отзыв',
'new_item' => 'Новый отзыв',
'view_item' => 'Просмотреть отзыв',
'search_items' => 'Поиск отзывов',
'not_found' => 'Отзывы не найдены',
'not_found_in_trash' => 'Отзывы не найдены в корзине',
);
$args = array(
'labels' => $labels,
'public' => false,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => false,
'supports' => array('title', 'editor', 'author'),
'menu_icon' => 'dashicons-testimonial',
);
register_post_type('wpall_review', $args);
}
add_action('init', 'wpall_register_reviews_cpt');
Этот код создаёт новый тип записи wpall_review, который будет доступен в админке для добавления и редактирования отзывов. Обратите внимание, что записи не публичные, чтобы отзывы не отображались как обычные посты.
Добавление мета-поля для рейтинга и статуса подтверждения
Чтобы к отзыву можно было добавить рейтинг, а также пометить его как подтверждённый или нет, добавим мета-поля. Для удобства используем стандартный add_meta_box и сохраняем данные через хук save_post.
function wpall_add_review_meta_boxes() {
add_meta_box('wpall_review_rating', 'Рейтинг отзыва', 'wpall_review_rating_meta_box', 'wpall_review', 'side', 'default');
add_meta_box('wpall_review_approved', 'Подтверждение отзыва', 'wpall_review_approved_meta_box', 'wpall_review', 'side', 'default');
}
add_action('add_meta_boxes', 'wpall_add_review_meta_boxes');
function wpall_review_rating_meta_box($post) {
$rating = get_post_meta($post->ID, '_wpall_review_rating', true);
?>
<label for="wpall_review_rating_field">Рейтинг (1-5): </label>
<select name="wpall_review_rating_field" id="wpall_review_rating_field">
<?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 wpall_review_approved_meta_box($post) {
$approved = get_post_meta($post->ID, '_wpall_review_approved', true);
?>
<label>
<input type="checkbox" name="wpall_review_approved_field" <?php checked($approved, 'yes'); ?> /> Подтверждён
</label>
<?php
}
function wpall_save_review_meta($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (isset($_POST['wpall_review_rating_field'])) {
update_post_meta($post_id, '_wpall_review_rating', intval($_POST['wpall_review_rating_field']));
}
$approved = isset($_POST['wpall_review_approved_field']) ? 'yes' : 'no';
update_post_meta($post_id, '_wpall_review_approved', $approved);
}
add_action('save_post_wpall_review', 'wpall_save_review_meta');
Теперь при редактировании отзыва вы можете ставить рейтинг и помечать отзыв как подтверждённый. Это позволит фильтровать отзывы на фронтенде.
Фронтенд: форма добавления отзывов с AJAX и проверкой данных
Для удобства пользователей создадим форму добавления отзывов на сайте, которая будет отправлять данные через AJAX. Это позволит избежать перезагрузки страницы и повысит отзывчивость интерфейса.
Добавим HTML формы и JavaScript для AJAX-запроса:
<form id="wpall-review-form">
<label>Ваше имя:<input type="text" name="author" required></label><br>
<label>Отзыв:<textarea name="content" required></textarea></label><br>
<label>Рейтинг:
<select name="rating" required>
<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>
</label><br>
<button type="submit">Отправить отзыв</button>
<div id="wpall-review-message"></div>
</form>
<script>
jQuery(document).ready(function($) {
$('#wpall-review-form').on('submit', function(e) {
e.preventDefault();
var data = {
action: 'wpall_submit_review',
author: $(this).find('input[name="author"]').val(),
content: $(this).find('textarea[name="content"]').val(),
rating: $(this).find('select[name="rating"]').val(),
nonce: '<?php echo wp_create_nonce("wpall_review_nonce"); ?>'
};
$.post('<?php echo admin_url("admin-ajax.php"); ?>', data, function(response) {
$('#wpall-review-message').text(response.data.message);
if(response.success) {
$('#wpall-review-form')[0].reset();
}
});
});
});
</script>
Обработка AJAX-запроса в functions.php
function wpall_handle_ajax_review() {
check_ajax_referer('wpall_review_nonce', 'nonce');
$author = sanitize_text_field($_POST['author']);
$content = sanitize_textarea_field($_POST['content']);
$rating = intval($_POST['rating']);
if (empty($author) || empty($content) || $rating < 1 || $rating > 5) {
wp_send_json_error(array('message' => 'Пожалуйста, заполните все поля корректно.'));
}
$review_post = array(
'post_title' => wp_trim_words($content, 5, '...'),
'post_content' => $content,
'post_status' => 'pending', // отзыв будет ждать подтверждения
'post_type' => 'wpall_review',
'post_author' => 0,
);
$post_id = wp_insert_post($review_post);
if ($post_id) {
update_post_meta($post_id, '_wpall_review_rating', $rating);
update_post_meta($post_id, '_wpall_review_approved', 'no');
wp_send_json_success(array('message' => 'Спасибо за отзыв! После проверки он появится на сайте.'));
} else {
wp_send_json_error(array('message' => 'Ошибка при добавлении отзыва. Попробуйте позже.'));
}
}
add_action('wp_ajax_wpall_submit_review', 'wpall_handle_ajax_review');
add_action('wp_ajax_nopriv_wpall_submit_review', 'wpall_handle_ajax_review');
Вывод подтверждённых отзывов на сайте с пагинацией
Чтобы показывать отзывы только после подтверждения администратором, сделаем WP_Query с параметром мета-запроса. Также реализуем простую пагинацию.
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'wpall_review',
'post_status' => 'publish',
'meta_key' => '_wpall_review_approved',
'meta_value' => 'yes',
'paged' => $paged,
'posts_per_page' => 5,
);
$query = new WP_Query($args);
if ($query->have_posts()) :
echo '<ul class="wpall-reviews-list">';
while ($query->have_posts()) : $query->the_post();
$rating = get_post_meta(get_the_ID(), '_wpall_review_rating', true);
echo '<li><strong>' . esc_html(get_the_title()) . '</strong><br>';
echo esc_html(get_the_content()) . '<br>';
echo 'Рейтинг: ' . intval($rating) . ' ⭐</li>';
endwhile;
echo '</ul>';
// пагинация
echo paginate_links(array(
'total' => $query->max_num_pages,
));
wp_reset_postdata();
else :
echo '<p>Отзывов пока нет.</p>';
endif;
Рекомендации по безопасности и расширению
При работе с пользовательским вводом крайне важно использовать sanitize_text_field, sanitize_textarea_field, проверять nonce и права доступа. Также вы можете расширить систему, добавив:
- Отправку уведомлений администратору о новых отзывах (например, через wp_mail)
- Возможность отвечать на отзывы через админку
- Поддержку CAPTCHA для защиты от спама
- Интеграцию с плагинами кеширования, например, Clearfy Pro, чтобы избежать проблем с кешем AJAX
Если хотите сделать систему отзывов более визуально привлекательной, обратите внимание на темы с поддержкой кастомных типов записей, например Reboot.