beget banner 468x60beget banner 728x90beget banner 930x180kwork banner 468x60kwork banner 728x90kwork banner 930x180smsc banner 468x60smsc banner 728x90smsc banner 930x180

Как создать AJAX-форму на WordPress без плагинов

WordPress имеет достаточно простую методологию обработки Ajax-запросов. Ajax-запросами называют такие запросы, которые происходят без перезагрузки страницы и в результате работа с сайтом становится быстрее и удобнее для конечного пользователя.

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

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

Создание формы

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

<form id="form" class="form">
	<label for="form_name">Ваше имя: </label>
	<input type="text" name="form_name" id="form_name" class="required form_name" placeholder="Александр Иванов" value=""/>

	<label for="form_tel">Номер телефона: </label>
	<input type="tel" name="form_tel" id="form_tel" class="required form_tel" inputmode="numeric" placeholder="+7 (___) ___-__-__" value="">

	<label for="form_message">Сообщение: </label>
	<textarea name="form_message" id="form_message" class="form_message" placeholder="Комментарий" rows="10" cols="30"></textarea>

	<input type="checkbox" name="form_anticheck" id="form_anticheck" class="form_anticheck" style="display: none !important;" value="true" checked="checked"/>
	<input type="text" name="form_submitted" id="form_submitted" value="" style="display: none !important;"/>

	<input type="submit" id="form_submit" class="button form_button" value="Отправить"/>
</form>

Подключение и локализация скриптов

Для работы этой формы необходимо создать js-файл и подключить его в файле functions.php с помощью хука wp_enqueue_scripts. Например, ajax-form.js. У меня этот файл находится в папке /assets/js/, компилируется и минифицируется галпом.

add_action( 'wp_enqueue_scripts', 'ajax_form_scripts' );
function ajax_form_scripts() {

	// Обработка полей формы
	wp_enqueue_script( 'jquery-form' );

	// Подключаем скрипты формы
	wp_enqueue_script( 'ajax-form', get_theme_file_uri( '/assets/js/ajax-form.min.js' ), array('jquery'), 1.0, true );
	wp_localize_script( 'ajax-form', 'ajax_form_object', array(
		'url'   => admin_url( 'admin-ajax.php' ),
		'nonce' => wp_create_nonce( 'ajax-form-nonce' ),
	) );

}
Если вы используете плагин кеширования, например WP Super Cache, то вы должны настроить его так, чтобы кеш очищался не реже, чем раз в сутки, т.к. функция wp_create_nonce() создает одноразовый код nonce на 24 часа и если он будет просрочен, то проверка формы будет вызывать ошибку

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

В js-файле скрипта мы отправляем поля формы в обработчик. Выводим ошибки, если что-то пошло не так или сообщение об успехе отправки.

jQuery(document).ready(function ($) {
    var form = $('#form');

    // Сбрасываем значения полей
    $('#form input, #form textarea').on('blur', function () {
        $('#form input, #form textarea').removeClass('error');
        $('.notification').remove();
        $('#form_submit').val('Отправить');
    });

    // Отправка значений полей
    var options = {
        url: ajax_form_object.url,
        data: {
            action: 'ajax_form_action',
            nonce: ajax_form_object.nonce
        },
        type: 'POST',
        dataType: 'json',
        beforeSubmit: function (xhr) {
            // При отправке формы меняем надпись на кнопке
            $('#form_submit').val('Отправляем...');
        },
        success: function (request, xhr, status, error) {

            if (request.success === true) {
                // Если все поля заполнены, отправляем данные и меняем надпись на кнопке
                form.after('<div class="notification notification_accept">' + request.data + '</div>').slideDown();
                $('#form_submit').val('Отправить');
            } else {
                // Если поля не заполнены, выводим сообщения и меняем надпись на кнопке
                $.each(request.data, function (key, val) {
                    $('.form_' + key).addClass('error');
                    $('.form_' + key).after('<div class="notification notification_warning notification_warning_' + key + '">' + val + '</div>');
                });
                $('#form_submit').val('Что-то пошло не так...');
            }
            // При успешной отправке сбрасываем значения полей
            $('#form')[0].reset();
        },
        error: function (request, status, error) {
            $('#form_submit').val('Что-то пошло не так...');
        }
    };
    // Отправка формы
    form.ajaxForm(options);
});

Создание обработчика формы

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

require_once get_stylesheet_directory() . '/includes/backend/handler.php';

Обработка ajax «подвешивается» на динамические хуки wp_ajax_ и wp_ajax_nopriv_. В нем мы проверяем nonce, дополнительные поля для защиты от спама и обрабатываем поля. Если в процессе у нас возникают ошибки, то мы возвращаем их в виде массива в js-скрипт. Если обработка полей проходит успешно, то мы собираем письмо, заголовки и отправляем с помощью функции wp_mail().

В поле $email_to вы должны указать email, на который будут отправляться письма. Советую указывать в этом поле email отличный от администратора, т.к. в противном случае, при отправке писем могут возникнуть ошибки у некоторых почтовых клиентов.

add_action( 'wp_ajax_ajax_form_action', 'ajax_action_callback' );
add_action( 'wp_ajax_nopriv_ajax_form_action', 'ajax_action_callback' );

function ajax_action_callback() {

	// Массив ошибок
	$errors = [];

	// Если не прошла проверка nonce, то блокируем отправку
	if ( !wp_verify_nonce( $_POST['nonce'], 'ajax-form-nonce' ) ) {
		wp_die( 'Данные отправлены с некорректного адреса' );
	}

	// Проверяем на спам. Если скрытое поле заполнено или снят чек, то блокируем отправку
	if ( $_POST['form_anticheck'] === false || !empty( $_POST['form_submitted'] ) ) {
		wp_die( 'Ты кто такой, давай, до свидания!' );
	}


	// Проверяем поле имени, если пустое, то пишем сообщение в массив ошибок
	if ( empty( $_POST['form_name'] ) || !isset( $_POST['form_name'] ) ) {
		$errors['name'] = 'Пожалуйста, введите ваше имя.';
	} else {
		$form_name = sanitize_text_field( $_POST['form_name'] );
	}

	// Проверяем поле ввода телефона, если пустое, то пишем сообщение в массив ошибок
	if ( empty( $_POST['form_tel'] ) || !isset( $_POST['form_tel'] ) ) {
		$errors['tel'] = 'Пожалуйста, введите номер телефона';
	} else {
		$form_tel = sanitize_text_field( $_POST['form_tel'] );
	}

	// Проверяем поле сообщения, если пустое, то пишем сообщение по умолчанию
	if ( empty( $_POST['form_message'] ) || !isset( $_POST['form_message'] ) ) {
		$form_message = 'Пустое сообщение с сайта';
	} else {
		$form_message = sanitize_text_field( $_POST['form_message'] );
	}


	// Проверяем массив ошибок, если не пустой, то передаем сообщение. Иначе отправляем письмо
	if ( $errors ) {

		wp_send_json_error( $errors );

	} else {

		// Узнаем с какого сайта пришло письмо
		$home_url = wp_parse_url( home_url() );
		$subject = 'Письмо с сайта ' . $home_url['host'];

		// Указываем адресаты
		$email_to = 'example@example.ru';
		$email_from = get_option( 'admin_email' );

		// Собираем письмо
		$body  = 'Имя: ' . $form_name . '\n';
		$body .= 'Телефон: ' . $form_tel . '\n';
		$body .= 'Сообщение: ' . $form_message . '\n';

		$headers = 'From: ' . $home_url['host'] . ' <' . $email_from . '>' . "\r\n" . 'Reply-To: ' . $email_from;

		// Отправляем
		wp_mail( $email_to, $subject, $body, $headers );

		// Отправляем сообщение об успешной отправке
		$message_success = 'Собщение отправлено. В ближайшее время мы с вами свяжемся';
		wp_send_json_success( $message_success );
	}

	// Убиваем процесс ajax
	wp_die();

}

Если все сделано верно, то у вас будет примерно такая форма. Она будет выводить ошибки и, что важнее, отправлять письма.

etxt banner 480x320etxt banner 728x90etxt banner 120x600skillbox banner 480x320skillbox banner 728x90skillbox banner 120x600flexbe banner 480x320flexbe banner 728x90flexbe banner 120x600

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 4 / 5. Количество оценок: 9

Оценок пока нет. Поставьте оценку первым.

Похожие посты

Как сделать webp без плагинов в WordPress

WebP — это современный формат сжатия изображений без потери качества, который напрямую влияет на скорость загрузки сайта. Конвертирование изображений из jpg и png в формат webp может дать существенный прирост в баллах по google page speed. Формат webp поддерживается большинством современных браузеров. Вы без труда можете найти плагины, которые помогут вам автоматически конвертировать изображения, добавленные…
Подробнее

Как вывести все изображения из произвольной папки без плагинов в WordPress

При разработке своих сайтов вам может понадобиться вывести галереи изображений из произвольных папок без их загрузки в библиотеку. Давайте рассмотрим пример, как это сделать с помощью шорткода: Использование: [folder-gallery path=’/data/images/’] Как видите, функция принимает путь до искомой папки (обязательно с открывающим и закрывающим слешем), в функции устанавливаются разрешенные типы изображений и формируется вывод с классами…
Подробнее

Как изменить выравнивание и размер изображения при вставке в редактор WordPress

При добавлении изображения в пост, по умолчанию WordPress вставляет его в размере medium и без выравнивания. Чтобы при загрузке картинки ей прописывалось выравнивание по центру и полный размер, вы можете использовать такой код:
Подробнее