Обратная связь — важный элемент любого сайта на 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.
Такой подход позволяет гибко настраивать логику работы формы, улучшать её и расширять в зависимости от требований проекта без зависимости от тяжёлых плагинов.