wp-lessons.ru wordpress WP-Lessons

Как создать динамическую форму обратной связи в WordPress с валидацией и сохранением данных

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

Почему стоит создавать собственную форму обратной связи

Стандартные плагины для форм (Contact Form 7, WPForms и другие) отлично подходят для большинства задач, но бывают ситуации, когда нужна гибкость и кастомизация, которую сложно реализовать через готовые решения. Например, динамическая валидация полей, сохранение заявок в отдельной таблице, интеграция с внешними сервисами или собственный дизайн.

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

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

Создание шорткода для формы обратной связи

Для начала создадим шорткод, который будет выводить HTML формы в любом месте сайта. Добавим следующий код в файл functions.php вашей темы или в отдельный плагин:

function wp_lessons_contact_form_shortcode() {
    ob_start();
    ?>
    <form id="wp-lessons-contact-form" method="post">
        <p>
            <label for="wp_lessons_name">Имя (обязательно)</label><br>
            <input type="text" id="wp_lessons_name" name="wp_lessons_name" required>
        </p>
        <p>
            <label for="wp_lessons_email">Email (обязательно)</label><br>
            <input type="email" id="wp_lessons_email" name="wp_lessons_email" required>
        </p>
        <p>
            <label for="wp_lessons_message">Сообщение (обязательно)</label><br>
            <textarea id="wp_lessons_message" name="wp_lessons_message" rows="5" required></textarea>
        </p>
        <p>
            <input type="hidden" name="wp_lessons_contact_nonce" value="<?php echo wp_create_nonce('wp_lessons_contact_nonce_action'); ?>">
            <button type="submit" name="wp_lessons_submit">Отправить</button>
        </p>
        <div id="wp_lessons_response"></div>
    </form>
    <?php
    return ob_get_clean();
}
add_shortcode('wp_lessons_contact_form', 'wp_lessons_contact_form_shortcode');

В этом коде мы создаём простой HTML с тремя обязательными полями и добавляем nonce для защиты от CSRF. Далее необходимо обработать данные при отправке формы.

Обработка отправки формы: валидация и сохранение данных

Для обработки формы используем хук init, который срабатывает на каждой загрузке WordPress, и проверим, отправлена ли наша форма:

function wp_lessons_handle_contact_form_submission() {
    if (!isset($_POST['wp_lessons_submit'])) {
        return;
    }

    // Проверка nonce для безопасности
    if (!isset($_POST['wp_lessons_contact_nonce']) || !wp_verify_nonce($_POST['wp_lessons_contact_nonce'], 'wp_lessons_contact_nonce_action')) {
        wp_die('Ошибка безопасности. Попробуйте обновить страницу и отправить форму снова.');
    }

    // Очистка и валидация данных
    $name = sanitize_text_field($_POST['wp_lessons_name']);
    $email = sanitize_email($_POST['wp_lessons_email']);
    $message = sanitize_textarea_field($_POST['wp_lessons_message']);

    if (empty($name) || empty($email) || empty($message)) {
        wp_die('Пожалуйста, заполните все обязательные поля.');
    }

    if (!is_email($email)) {
        wp_die('Введите корректный email.');
    }

    // Дополнительная защита от спама: простой honeypot
    if (!empty($_POST['wp_lessons_hp'])) {
        wp_die('Обнаружен спам.');
    }

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

    // Создаём таблицу, если её ещё нет
    $charset_collate = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE IF NOT EXISTS $table_name (
        id mediumint(9) NOT NULL AUTO_INCREMENT,
        name tinytext NOT NULL,
        email varchar(100) NOT NULL,
        message text NOT NULL,
        date datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        PRIMARY KEY  (id)
    ) $charset_collate;";
    require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
    dbDelta($sql);

    // Вставляем данные
    $wpdb->insert(
        $table_name,
        array(
            'name' => $name,
            'email' => $email,
            'message' => $message,
            'date' => current_time('mysql')
        )
    );

    echo '<p class="wp-lessons-success">Спасибо за ваше сообщение! Мы свяжемся с вами в ближайшее время.</p>';
    exit;
}
add_action('init', 'wp_lessons_handle_contact_form_submission');

Этот код проверяет nonce, валидирует и очищает данные, создаёт таблицу в базе, если её нет, и сохраняет сообщение пользователя. Для защиты от спама использован простой honeypot, который можно добавить в форму (например, скрытое поле).

Добавление honeypot поля в форму

Чтобы добавить honeypot, нужно внести в форму следующий скрытый input, который обычный посетитель не увидит, а боты заполнить могут:

<input type="text" name="wp_lessons_hp" style="display:none" tabindex="-1" autocomplete="off">

Если поле заполнено — считаем, что это спам.

Клиентская валидация на JavaScript для улучшения UX

Чтобы пользователю было удобнее, добавим простую проверку на стороне клиента. Для этого подключим скрипт, который будет проверять поля перед отправкой и выводить ошибки.

Добавим функцию в functions.php для подключения скрипта:

function wp_lessons_enqueue_scripts() {
    wp_enqueue_script('wp-lessons-contact-js', get_template_directory_uri() . '/js/wp-lessons-contact.js', array('jquery'), '1.0', true);
}
add_action('wp_enqueue_scripts', 'wp_lessons_enqueue_scripts');

Создайте файл js/wp-lessons-contact.js в вашей теме со следующим содержимым:

jQuery(document).ready(function($) {
    $('#wp-lessons-contact-form').on('submit', function(e) {
        let hasError = false;
        $('#wp_lessons_response').empty();

        const name = $('#wp_lessons_name').val().trim();
        const email = $('#wp_lessons_email').val().trim();
        const message = $('#wp_lessons_message').val().trim();

        if (name.length === 0) {
            hasError = true;
            $('#wp_lessons_response').append('<p>Пожалуйста, введите имя.</p>');
        }

        if (email.length === 0) {
            hasError = true;
            $('#wp_lessons_response').append('<p>Пожалуйста, введите email.</p>');
        } else {
            const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            if (!emailReg.test(email)) {
                hasError = true;
                $('#wp_lessons_response').append('<p>Введите корректный email.</p>');
            }
        }

        if (message.length === 0) {
            hasError = true;
            $('#wp_lessons_response').append('<p>Пожалуйста, введите сообщение.</p>');
        }

        if (hasError) {
            e.preventDefault();
        }
    });
});

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

Дополнительные рекомендации по безопасности и функционалу

Защита от спама

Помимо honeypot, можно использовать reCAPTCHA от Google или плагин Akismet для фильтрации спама. Реализовать reCAPTCHA можно через API, добавив соответствующие поля и проверку на сервере.

Отправка уведомлений администратору

Чтобы не пропустить сообщения, можно отправлять email с содержимым формы. Добавим в обработчик после сохранения в базу такой код:

$to = get_option('admin_email');
$subject = 'Новое сообщение с формы обратной связи';
$body = "Имя: $name<br>Email: $email<br>Сообщение:<br>$message";
$headers = array('Content-Type: text/html; charset=UTF-8');
wp_mail($to, $subject, $body, $headers);

Вывод сохранённых сообщений в админке

Для удобства можно создать страницу в админке с таблицей сообщений. Это чуть более сложная задача, но она позволит обрабатывать заявки прямо из WordPress без сторонних сервисов.

Для этого используйте хуки admin_menu и WP_List_Table, чтобы создать кастомный интерфейс.

Итог

Создание собственной формы обратной связи в WordPress — несложная, но полезная задача, которая даёт полный контроль над процессом сбора и обработки сообщений. Мы рассмотрели, как сделать динамическую форму с клиентской и серверной валидацией, защитой от спама, сохранением данных в базе и базовой интеграцией с email.

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