Как использовать AJAX для отзывов в WordPress без перезагрузки страницы

В современных сайтах важна интерактивность и удобство для пользователя. Один из классических примеров — форма отзывов, которая должна работать без перезагрузки страницы. В этой статье мы подробно разберем, как реализовать отправку отзывов через AJAX в WordPress, сохраняя отзывы в базе и выводя их сразу после отправки.

Почему использовать AJAX для отзывов в WordPress

Традиционный способ отправки формы отзывов подразумевает перезагрузку страницы, что ухудшает пользовательский опыт. AJAX позволяет отправлять данные на сервер асинхронно, не прерывая работу на странице. Это ускоряет процесс, снижает нагрузку на сервер и делает интерфейс более отзывчивым.

Кроме того, AJAX поможет вам избежать повторной отправки формы при обновлении страницы и легко интегрируется с кастомными типами постов или пользовательскими таблицами базы данных.

Создаем таблицу для отзывов в базе данных WordPress

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

function wpcodex_create_reviews_table() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpcodex_reviews';
    $charset_collate = $wpdb->get_charset_collate();

    $sql = "CREATE TABLE $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        name varchar(100) NOT NULL,
        email varchar(100) NOT NULL,
        review text NOT NULL,
        rating tinyint(1) NOT NULL,
        created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        PRIMARY KEY  (id)
    ) $charset_collate;";

    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );
}
register_activation_hook( __FILE__, 'wpcodex_create_reviews_table' );

Этот код создаст таблицу wp_wpcodex_reviews (предполагается префикс wp_, у вас может быть другой), где хранятся имя, email, текст отзыва, рейтинг и дата создания.

Форма отзывов с AJAX

Создадим форму для отправки отзывов и подключим скрипт на jQuery, который будет отправлять данные на сервер.

<form id="wpcodex-review-form">
    <input type="text" name="name" placeholder="Ваше имя" required />
    <input type="email" name="email" placeholder="Ваш email" required />
    <textarea name="review" placeholder="Ваш отзыв" required></textarea>
    <select name="rating" required>
        <option value="5">5 – Отлично</option>
        <option value="4">4 – Хорошо</option>
        <option value="3">3 – Нормально</option>
        <option value="2">2 – Плохо</option>
        <option value="1">1 – Очень плохо</option>
    </select>
    <button type="submit">Отправить отзыв</button>
</form>

<div id="wpcodex-review-response"></div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
jQuery(document).ready(function($) {
    $('#wpcodex-review-form').on('submit', function(e) {
        e.preventDefault();
        var formData = $(this).serialize();
        $.ajax({
            url: wpcodex_ajax_object.ajax_url,
            type: 'POST',
            data: {
                action: 'wpcodex_submit_review',
                data: formData,
                security: wpcodex_ajax_object.nonce
            },
            success: function(response) {
                $('#wpcodex-review-response').html(response.data.message);
                if (response.success) {
                    $('#wpcodex-review-form')[0].reset();
                    wpcodex_load_reviews();
                }
            },
            error: function() {
                $('#wpcodex-review-response').html('Произошла ошибка. Попробуйте позже.');
            }
        });
    });

    function wpcodex_load_reviews() {
        $.ajax({
            url: wpcodex_ajax_object.ajax_url,
            type: 'POST',
            data: { action: 'wpcodex_get_reviews' },
            success: function(response) {
                $('#wpcodex-review-list').html(response);
            }
        });
    }

    wpcodex_load_reviews();
});
</script>

<div id="wpcodex-review-list"></div>

Обратите внимание, что для безопасного выполнения AJAX мы используем nonce, а для удобства работы — локализацию скрипта, которую добавим далее.

Обработка AJAX-запросов в WordPress

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

add_action('wp_enqueue_scripts', 'wpcodex_enqueue_scripts');
function wpcodex_enqueue_scripts() {
    wp_enqueue_script('jquery');
    wp_localize_script('jquery', 'wpcodex_ajax_object', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce'    => wp_create_nonce('wpcodex_nonce')
    ));
}

add_action('wp_ajax_wpcodex_submit_review', 'wpcodex_submit_review_callback');
add_action('wp_ajax_nopriv_wpcodex_submit_review', 'wpcodex_submit_review_callback');

function wpcodex_submit_review_callback() {
    check_ajax_referer('wpcodex_nonce', 'security');

    parse_str($_POST['data'], $form_data);

    $name = sanitize_text_field($form_data['name']);
    $email = sanitize_email($form_data['email']);
    $review = sanitize_textarea_field($form_data['review']);
    $rating = intval($form_data['rating']);

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

    global $wpdb;
    $table_name = $wpdb->prefix . 'wpcodex_reviews';

    $inserted = $wpdb->insert(
        $table_name,
        array(
            'name' => $name,
            'email' => $email,
            'review' => $review,
            'rating' => $rating,
            'created_at' => current_time('mysql')
        ),
        array('%s', '%s', '%s', '%d', '%s')
    );

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

add_action('wp_ajax_wpcodex_get_reviews', 'wpcodex_get_reviews_callback');
add_action('wp_ajax_nopriv_wpcodex_get_reviews', 'wpcodex_get_reviews_callback');

function wpcodex_get_reviews_callback() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'wpcodex_reviews';

    $reviews = $wpdb->get_results("SELECT name, review, rating, created_at FROM $table_name ORDER BY created_at DESC LIMIT 10");

    if (empty($reviews)) {
        echo '<p>Пока нет отзывов.</p>';
    } else {
        echo '<ul class="wpcodex-reviews-list">';
        foreach ($reviews as $r) {
            $stars = str_repeat('★', $r->rating) . str_repeat('☆', 5 - $r->rating);
            echo '<li><strong>' . esc_html($r->name) . '</strong> <span>' . $stars . '</span><br/><em>' . esc_html($r->review) . '</em><br/><small>' . esc_html(date('d.m.Y H:i', strtotime($r->created_at))) . '</small></li>';
        }
        echo '</ul>';
    }
    wp_die();
}

Подключение и использование

Чтобы интегрировать этот функционал, создайте плагин с приведённым кодом или добавьте его в файл functions.php вашей темы. Вставьте форму отзывов в нужное место сайта через шорткод или напрямую в шаблон.

Пример шорткода для вывода формы:

function wpcodex_review_form_shortcode() {
    ob_start();
    ?>
    <form id="wpcodex-review-form">
        <input type="text" name="name" placeholder="Ваше имя" required />
        <input type="email" name="email" placeholder="Ваш email" required />
        <textarea name="review" placeholder="Ваш отзыв" required></textarea>
        <select name="rating" required>
            <option value="5">5 – Отлично</option>
            <option value="4">4 – Хорошо</option>
            <option value="3">3 – Нормально</option>
            <option value="2">2 – Плохо</option>
            <option value="1">1 – Очень плохо</option>
        </select>
        <button type="submit">Отправить отзыв</button>
    </form>

    <div id="wpcodex-review-response"></div>
    <div id="wpcodex-review-list"></div>
    <?php
    return ob_get_clean();
}
add_shortcode('wpcodex_review_form', 'wpcodex_review_form_shortcode');

Добавьте шорткод [wpcodex_review_form] в нужный пост или страницу, и форма с отзывами будет работать с AJAX без перезагрузки.

Советы по безопасности и доработке

Используйте check_ajax_referer для защиты от CSRF. Всегда фильтруйте и валидируйте данные с помощью функций WordPress.

Для улучшения UX можно добавить спиннер загрузки, уведомления об ошибках валидации прямо на форме, а также пагинацию или фильтры для отзывов.

Если у вас много отзывов, стоит подумать о кешировании вывода, например, с помощью transient API.

Использование с плагинами WPSHOP

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

⭐⭐⭐⭐⭐