WordPress. Форма обратной связи без плагинов и без перезагрузки • 1 • WPRUSe

WordPress. Форма обратной связи без плагинов и без перезагрузки

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

Для тех кто хочет разобраться или по какой-то причине не любит плагины.

Хотя плагином сделать подобную форму можно без проблем — это будет быстрее, проще и удобнее. Например, плагином Simple Basic Contact Form.

Итак, создаем форму обратной связи без плагина. Алгоритм простой

  1. Создание и вывод формы
  2. Подключение ajax
  3. Подключение обработчика

Приступим.

Внимание! Код добавлять в файл functions.php дочерней темы или пустой плагин.

к содержанию

1. Создаем и выводим форму

Форму можно выводить напрямую в файле страницы. Например, сделать шаблон страницы и в нем выводить. Или сделать шорткод и через него выводить в нужном месте. Вот шорткод и будем использовать.

add_shortcode( 'art_feedback', 'art_feedback' );
/**
 * Шорткод вывода формы
 *
 * @return string
 * @see https://wpruse.ru/?p=3224
 */
function art_feedback() {

	ob_start();
	?>
	<form id="add_feedback">
		<input type="text" name="art_name" id="art_name" class="required art_name" placeholder="Ваше имя" value=""/>

		<input type="email" name="art_email" id="art_email" class="required art_email" placeholder="Ваш E-Mail" value=""/>

		<input type="text" name="art_subject" id="art_subject" class="art_subject" placeholder="Тема сообщения" value=""/>

		<textarea name="art_comments" id="art_comments" placeholder="Сообщение" rows="10" cols="30" class="required art_comments"></textarea>

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

		<input type="text" name="art_submitted" id="art_submitted" value="" style="display: none !important;"/>

		<input type="submit" id="submit-feedback" class="button" value="Отправить сообщение"/>
	</form>
	<?php

	return ob_get_clean();
}

Теперь создаем страницу и выводим на ней шорткод.

WordPress. Форма обратной связи без плагинов и без перезагрузки • 2 • WPRUSe

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

WordPress. Форма обратной связи без плагинов и без перезагрузки • 3 • WPRUSe
к содержанию

2. Внешний вид формы

Добавим красоты нашей форме.

/*
* Внешний вид формы
*/
#add_feedback {
    margin: 20px 0 0;
    position: relative;
}

#art_name, #art_email, #art_subject, #art_comments {
    padding: 10px 5px;
    display: inline-block;
    width: 49.548%;
    border-radius: 3px;
    border: 1px solid #ddd;
    font-size: 0.9em;
}

#art_subject {
    width: 100%;
    margin: 5px 0;
}

#art_comments {
    width: 100%;
}

#add_feedback .button {
    border: none;
    padding: 10px 20px;
    color: #fff;
    font-size: 1em;
    display: inherit;
    margin: 10px 0 0 0;
    border-radius: 3px;
    background-color: #2f94ce;
}

#add_feedback input[type="text"]:focus, #add_feedback input[type="password"]:focus, #add_feedback input[type="email"]:focus, #add_feedback textarea:focus {
    color: #444;
    box-shadow: 0 0 3px rgba(68, 68, 68, 0.2);
}

.error-text {
    background: #F59E9E;
    padding: 15px 0px;
    text-align: center;
    color: #fff;
}

.error-name, .error-email, .error-comments {
    display: inline-block;
    font-size: 11px;
    position: absolute;
    top: -30px;
    color: white;
    border: 1px solid red;
    padding: 5px 10px;
    line-height: 1.1;
    background: red;
    box-shadow: 0 0 3px 0px rgba(0, 0, 0, 0.3);
}

.error-name:after, .error-email:after, .error-comments:after {
    content: '';
    position: absolute;
    left: 20px;
    bottom: -10px;
    border: 5px solid transparent;
    border-top: 5px solid red;
}

.error-comments {
    top: 16%;
    left: 0;
}

.error-name {

    left: 0;
}

.error-email {
    right: 4%;
}

.message-success {
    background: rgba(0, 128, 0, 0.5);
    color: #fff;
    padding: 20px;
    text-align: center;
    margin: 20px auto;
    border-radius: 3px;
}

#add_feedback .error {
    border: 1px solid red;

}

#add_feedback .required:after {
    content: '*';
    position: absolute;
    left: 20px;
    bottom: -10px;
}

#art_name:focus::-moz-placeholder,
#art_name:focus:-moz-placeholder,
#art_name:focus:-ms-input-placeholder,
#art_email:focus::-webkit-input-placeholder,
#art_email:focus::-moz-placeholder,
#art_email:focus:-moz-placeholder,
#art_email:focus:-ms-input-placeholder,
#art_comments:focus::-webkit-input-placeholder,
#art_comments:focus::-moz-placeholder,
#art_comments:focus:-moz-placeholder,
#art_comments:focus:-ms-input-placeholder,
#art_subject:focus::-webkit-input-placeholder,
#art_subject:focus::-moz-placeholder,
#art_subject:focus:-moz-placeholder,
#art_subject:focus:-ms-input-placeholder {
    color: transparent
}

Вот так теперь выглядит форма.

WordPress. Форма обратной связи без плагинов и без перезагрузки • 4 • WPRUSe
к содержанию

3. Работа формы

Теперь заставим форму работать.

Создание и подключение нужных файлов

Для работы формы потребуется создать файл js. Например, feedback.js. Файл необходимо создать в папке дочерней темы. Или в соответсвующей папке плагина.

Теперь через файл functions.php подключаем нужное.

add_action( 'wp_enqueue_scripts', 'art_feedback_scripts' );
/**
 * Подключение файлов скрипта формы обратной связи
 *
 * @see https://wpruse.ru/?p=3224
 */
function art_feedback_scripts() {

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

	// Подключаем файл скрипта
	wp_enqueue_script(
		'feedback',
		get_stylesheet_directory_uri() . '/js/feedback.js',
		array( 'jquery' ),
		1.0,
		true
	);

	// Задаем данные обьекта ajax
	wp_localize_script(
		'feedback',
		'feedback_object',
		array(
			'url'   => admin_url( 'admin-ajax.php' ),
			'nonce' => wp_create_nonce( 'feedback-nonce' ),
		)
	);

}

После подключения в исходном коде должно быть видно подключение и вывод скрипта.

WordPress. Форма обратной связи без плагинов и без перезагрузки • 5 • WPRUSe
к содержанию

Отправка данных формы через ajax

В подключенный файл feedback.jsдобавляем отправку данных формы.

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

    // Сброс значений полей
    $('#add_feedback input, #add_feedback textarea').on('blur', function () {
        $('#add_feedback input, #add_feedback textarea').removeClass('error');
        $('.error-name,.error-email,.error-comments,.message-success').remove();
        $('#submit-feedback').val('Отправить сообщение');
    });

    // Отправка значений полей
    var options = {
        url: feedback_object.url,
        data: {
            action: 'feedback_action',
            nonce: feedback_object.nonce
        },
        type: 'POST',
        dataType: 'json',
        beforeSubmit: function (xhr) {
            // При отправке формы меняем надпись на кнопке
            $('#submit-feedback').val('Отправляем...');
        },
        success: function (request, xhr, status, error) {
            
            if (request.success === true) {
                // Если все поля заполнены, отправляем данные и меняем надпись на кнопке
                add_form.after('<div class="message-success">' + request.data + '</div>').slideDown();
                $('#submit-feedback').val('Отправить сообщение');
            } else {
                // Если поля не заполнены, выводим сообщения и меняем надпись на кнопке
                $.each(request.data, function (key, val) {
                    $('.art_' + key).addClass('error');
                    $('.art_' + key).before('<span class="error-' + key + '">' + val + '</span>');
                });
                $('#submit-feedback').val('Что-то пошло не так...');

            }
            // При успешной отправке сбрасываем значения полей
            $('#add_feedback')[0].reset();
        },
        error: function (request, status, error) {
            $('#submit-feedback').val('Что-то пошло не так...');
        }
    };
    // Отправка формы
    add_form.ajaxForm(options);
});

Если все верно подключено, при отправке данных скрипт будет срабатывать и выдавать ошибку.

WordPress. Форма обратной связи без плагинов и без перезагрузки • 6 • WPRUSe
к содержанию

Обработка Ajax

Теперь требуется написать обработчик скрипта. Напоминаю, обработка ajax «подвешивается» на динамические хуки wp_ajax_ и wp_ajax_nopriv_и требуется проверка nonce.

add_action( 'wp_ajax_feedback_action', 'ajax_action_callback' );
add_action( 'wp_ajax_nopriv_feedback_action', 'ajax_action_callback' );
/**
 * Обработка скрипта
 *
 * @see https://wpruse.ru/?p=3224
 */
function ajax_action_callback() {

	// Массив ошибок
	$err_message = array();

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

	// Проверяем на спам. Если скрытое поле заполнено или снят чек, то блокируем отправку
	if ( false === $_POST['art_anticheck'] || ! empty( $_POST['art_submitted'] ) ) {
		wp_die( 'Пошел нахрен, мальчик!(c)' );
	}

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

	// Проверяем полей емайла, если пустое, то пишем сообщение в массив ошибок
	if ( empty( $_POST['art_email'] ) || ! isset( $_POST['art_email'] ) ) {
		$err_message['email'] = 'Пожалуйста, введите адрес вашей электронной почты.';
	} elseif ( ! preg_match( '/^[[:alnum:]][a-z0-9_.-]*@[a-z0-9.-]+\.[a-z]{2,4}$/i', $_POST['art_email'] ) ) {
		$err_message['email'] = 'Адрес электронной почты некорректный.';
	} else {
		$art_email = sanitize_email( $_POST['art_email'] );

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

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

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

		wp_send_json_error( $err_message );

	} else {

		// Указываем адресата
		$email_to = '';

		// Если адресат не указан, то берем данные из настроек сайта
		if ( ! $email_to ) {
			$email_to = get_option( 'admin_email' );
		}

		$body    = "Имя: $art_name \nEmail: $art_email \n\nСообщение: $art_comments";
		$headers = 'From: ' . $art_name . ' <' . $email_to . '>' . "\r\n" . 'Reply-To: ' . $email_to;

		// Отправляем письмо
		wp_mail( $email_to, $art_subject, $body, $headers );

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

	// На всякий случай убиваем еще раз процесс ajax
	wp_die();

}
к содержанию

Заключение

Вот и все. Если все сделано правильно, то при отправке пустой формы будут такие сообщения.

WordPress. Форма обратной связи без плагинов и без перезагрузки • 7 • WPRUSe

Если отправка прошла успешно, то появится соответствующее сообщение

WordPress. Форма обратной связи без плагинов и без перезагрузки • 8 • WPRUSe

На этом все. Если есть вопросы и предложения пишите в комментариях. Удачи!