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_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();
}
Если все сделано верно, то у вас будет примерно такая форма. Она будет выводить ошибки и, что важнее, отправлять письма.