Всем привет!
Сегодня рассмотрим как в WordPress отправлять формы c помощью ajax’a и сохранять отправленные письма в админке, Вы удивитесь, как на самом деле все просто.
Такой механизм задействован в одном из проектов 2015 в котором я участвовал, спасибо Сереге!
Пример я буду показывать на стандартной теме Twenty Fifteen, в процессе работы мы пройдем следующие этапы
- Создадим шаблон с формой и подключим его в подвале сайта
- Подключим стили и JS
- Создадим произвольный тип записи mail где будут храниться отправленные письма
- Напишем функцию обработки формы
Шаблон формы обратной связи
Создадим в папке inc
файл contact-form.php
, со следующим кодом:
<form action="<?php echo admin_url('admin-ajax.php?action=send_mail'); ?>" method="post" class="form-send-mail"> <div class="form-view"> <h4><?php _e('Написать сейчас'); ?></h4> <div class="form-field"> <input type="text" id="client_fio" name="client_fio" placeholder="<?php _e('Ваше имя'); ?>" class="req-field"/> </div> <div class="form-field"> <input type="text" id="client_mail" name="client_mail" placeholder="<?php _e('Ваш e-mail'); ?>" class="req-field rf-mail"/> </div> <div class="form-field"> <textarea id="client_quest" name="client_quest" placeholder="<?php _e('Ваше сообщение'); ?>" class="req-field"></textarea> </div> <div class="form-submit"> <button type="submit"><?php _e('Отправить'); ?></button> </div> </div> <div class="form-is-sending"> <span class="pa-spinner"></span> </div> <div class="form-is-more"> <button type="button"> <?php _e('Отправить еще'); ?> </button> </div> </form>
Пройдемся по форме
- В атрибуте
action
указываем путь к обработчику нашей формы, в WordPress это файлadmin-ajax.php
, сама функция оработки данныхsend_mail
описывается в файлеfunctions.php
- Контейнер
div.form-view
содержит поля формы и кнопку ‘отправки / отмены’ сообщения - Контейнер
div.form-is-sending
отображает лоадер, по умолчанию скрыт и расположен по центру блока с формой - В контейнере
div.form-is-more
находится кнопка ‘Отправить еще’, по умолчанию скрыта и расположена по центру блока с формой - Поля из которых мы будем собирать данные должны иметь заполненый атрибут name и класс
.req-field
— для проверки
Выведем форму в футере
Открываем файл footer.php
и с помощью get_template_part()
выводим контакную форму:
<footer id="colophon" class="site-footer" role="contentinfo"> <?php get_template_part('inc/contact-form'); ?> <div class="site-info">
Займемся стилями и js’ом
Создадим в папке js
файл с названием contact-form.js
, а в папке css
файл с название contact-form.css
.
Откроем файл functions.php
, найдем в нем функцию twentyfifteen_scripts()
и подключим в ней наши стили и js для формы:
// Load contact form style wp_enqueue_style('contact-form-style', get_template_directory_uri() . '/css/contact.css', array(), '20170101'); // Load contact form js wp_enqueue_script('contact-form-js', get_template_directory_uri() . '/js/contact-form.js', array(), '20170101', true);
Оформление формы
я уже давненько юзаю Sass
, поэтому обычный CSS
Вы увидите, только в исходниках. Итак файл contact-form.css
будет содержать ниже приведенный сконвертированный Sass
:
.form-style { padding: 30px 0; background-color: #fff; position: relative; min-height: 400px; h4 { display: block; margin-bottom: 20px; font-size: 20px; } .form-view { position: relative; transition: opacity .3s, visibility .3s; } .form-is-sending { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 2; opacity: 0; visibility: hidden; transition: opacity .3s, visibility .3s; } .form-is-more { position: absolute; top: 50%; left: 50%; width: auto; height: auto; transform: translate(-50%, -50%); z-index: 3; opacity: 0; visibility: hidden; transition: opacity .3s, visibility .3s; } &.is-sending { .form-view { opacity: 0; visibility: hidden; } .form-is-sending { opacity: 1; visibility: visible; } } &.is-sending-complete { .form-view { opacity: 0; visibility: hidden; } .form-is-more { opacity: 1; visibility: visible; } } } .form-field { margin-bottom: 15px; input[type="text"], input[type="password"], input[type="email"], textarea { border: 0; border-bottom: 1px solid rgba(#000, .1); transition: border-color .3s; padding: 0 10px; width: 100%; box-sizing: border-box; height: 40px; font-family: Helvetica, Arial, sans-serif; font-size: 16px; color: #444; background: transparent; &.rf-error { border-color: #f04040; } } textarea { height: 100px; padding: 10px; overflow: auto; resize: none; } } .pa-spinner { position: absolute; top: 50%; left: 50%; width: 50px; height: 50px; z-index: 1; margin: -25px 0 0 -25px; border: 3px solid #ebebeb; border-radius: 50%; border-left-color: transparent; border-right-color: transparent; animation: cssload-spin 1325ms infinite linear; } @keyframes cssload-spin { 100% { transform: rotate(360deg); } } @media screen and (min-width: 59.6875em) { .form-style { padding: 30px 10%; } }
Пояснять тут особо нечего, это стили) играйте как хотите
Скриптик
jQuery(document).ready(function($){ var form = $('.form-send-mail'), action = form.attr('action'), pattern = /^([a-z0-9_\.-])+@[a-z0-9-]+\.([a-z]{2,4}\.)?[a-z]{2,4}$/i; form.find('.req-field').addClass('empty-field'); function checkInput() { form.find('.req-field').each(function () { var el = $(this); if (el.hasClass('rf-mail')) { if (pattern.test(el.val())) { el.removeClass('empty-field'); } else { el.addClass('empty-field'); } } else if (el.val() != '') { el.removeClass('empty-field'); } else { el.addClass('empty-field'); } }); } function lightEmpty() { form.find('.empty-field').addClass('rf-error'); setTimeout(function () { form.find('.rf-error').removeClass('rf-error'); }, 1000); } $(document).on('submit', '.form-send-mail', function (e) { var formData = { client_fio: $('#client_fio').prop('value'), client_mail: $('#client_mail').prop('value'), client_quest: $('#client_quest').prop('value') }; $.ajax({ type: 'POST', url: action, data: formData, beforeSend: function () { form.addClass('is-sending'); }, error: function (request, txtstatus, errorThrown) { console.log(request); console.log(txtstatus); console.log(errorThrown); }, success: function () { form.removeClass('is-sending').addClass('is-sending-complete'); } }); e.preventDefault(); }); $(document).on('click', '.form-send-mail button[type="submit"]', function (e) { checkInput(); var errorNum = form.find('.empty-field').length; if (errorNum > 0) { lightEmpty(); e.preventDefault(); } }); $(document).on('click', '.form-is-more button', function () { form.find('input').val(''); form.find('textarea').val(''); form.removeClass('is-sending-complete'); }); });
Скрипт очень простой:
- Объявляем переменные необходимые нам для работы — форма, путь к обработчику формы и патерн для проверки мыла
- Всем обязательным полям добавляем класс
empty-field
- Функция
checkInput()
проверяет поля на заполненность и корректность email’а - Функция
lightEmpty()
подсвечивает проблемные поля классомrf-error
- Далее пишем обработчик отправки формы (о нем ниже подробней)
- Следующим шагом описываем клик по кнопке отправки формы — по клику запускается функция
checkInput()
, считаем к-во ошибочных полей, если они есть то запускается функцияlightEmpty()
и процесс прекращается, в противном случае происходит обработка отправки формы - И финальный этап это клик по кнопке «Отправить еще» — по клику очищаются поля формы и у формы удаляется класс, который показывает кнопку
Обработчик отправки формы:
- в массив
formData
— собираем данные формы - запускаем Ajax обработчик
- в фукнции
beforeSend
добавляем форме классis-sending
— тоесть скрываем форму и показывается лоадер - в фукнции
error
— если он есть то в консоль выводятся всевозможные ошибки - в фукнции
success
у формы удаляется классis-sending
и добавляется классis-sending-complete
— то есть скрывается лоадер и форма, а показывается кнопка с предложением отправить еще одну форму - предотвращаем обычное поведение элемента — перезагрузку страницы
Итак на данном этапе мы получили красиво оформленную форму в подвале сайта, для которой осталось написать php обработчик для полученных данных.
Создадим произвольный тип записи
Произвольный тип записи нужен для хранения отправленных писем в базе данных сайта, соответственно письма будут доступны из админки WordPress. Открываем файл functions.php
и в самом низу добавляем следующий код:
add_action( 'init', 'cpt_mail_calback' ); function cpt_mail_calback() { $labels = array( "name" => "Mail", "singular_name" => "Mail", "menu_name" => "Mail", "all_items" => "All mail", "add_new" => "Add New", "add_new_item" => "Add New", "edit" => "Edit", "edit_item" => "Edit", "new_item" => "New item", "view" => "View", "view_item" => "View item", "search_items" => "Search item", "not_found" => "No found", "not_found_in_trash" => "No found", ); $args = array( "labels" => $labels, "description" => "", "public" => true, "show_ui" => true, "has_archive" => false, "show_in_menu" => true, "exclude_from_search" => true, "capability_type" => "post", "map_meta_cap" => true, "hierarchical" => true, "rewrite" => false, "query_var" => true, "menu_position" => 7, "menu_icon" => "dashicons-email-alt", "supports" => array( "title", "editor" ), ); register_post_type( "mail", $args ); }
Сохраним файл, обновим админку и увидим в меню пункт «Mail», в этом произвольном типе записи будут хранится все отправленные нам письма. Следующим шагом опишем функцию обработки ajax запроса send_mail()
.
Ajax обработчик формы
function send_mail() { /* Забираем отправленные данные */ $client_fio = $_POST['client_fio']; $client_mail = $_POST['client_mail']; $client_quest = $_POST['client_quest']; /* Отправляем нам письмо */ $emailTo = 'admin@test.com'; $subject = 'Test mail рассылки!'; $headers = "Content-type: text/html; charset=\"utf-8\""; $mailBody = "$client_fio <br/><br/> $client_mail <br/><br/> $client_quest"; wp_mail($emailTo, $subject, $mailBody, $headers); /* Создаем новый пост-письмо */ $post_data = array( 'post_title' => $client_fio, 'post_content' => $client_quest . '<br/>' .$client_mail, 'post_status' => 'publish', 'post_author' => 1, 'post_type' => 'mail', ); wp_insert_post( $post_data ); /* Завершаем выполнение ajax */ die(); } add_action("wp_ajax_send_mail", "send_mail"); add_action("wp_ajax_nopriv_send_mail", "send_mail");
Все. Обработчик формы готов, теперь смело заходим на наш локальный сайт, заполняем или не заполняем поля, кликаем по отправке, дозаполняем поля, чтобы форма отправилась, кликаем еще раз отправить… и все готово. Форма отправлена, можем отправить еще раз если сильно охота, переходим в админку и видим что у нас появилась новая запись с информацией отправленного письма. Ура!)
Послесловие #1
Будет ситуация когда Вам не нужно хранить письма в админке, это 100% )
В таком случае, пропускаем шаг создания произвольного типа записи и из функции send_mail()
удаляем создание нового поста и пользуемся.
Послесловие #2
Если хотите отправить письмо на несколько email адресов, то их нужно перечислить через запятую:
$emailTo = 'admin@test.com, sale@test.com, info@test.com';
Послесловие #3
Бонус #1 — Заменяем имя отправителя
function htm_mail_name( $email ){ return 'Howtomake'; } add_filter( 'wp_mail_from_name', 'htm_mail_name' );
Бонус #2 — Заменяем email отправителя
function htm_mail_from ($email ){ return 'info@howtomake.com.ua'; } add_filter( 'wp_mail_from', 'htm_mail_from' );
Заключение
Это первая полноценная статья за последние… года 2-4 (может дольше) извиняйте, что редко пишу..
У Вас теперь есть полноценный инструмент для отправки и обработки практически любых форм в WordPress. Вопросы, пожелания, непонятки и благодарности пишите в комментариях. Всем хорошего настроения
Архив сделан криворуко. CSS не соответствует написанному sass. Так же перепутаны form-style и form-send-mail.
Короче статья и архив требует доработки.
Дмитрий, все правильно) в
action
мы указываем php фукнцию которая обработает форму и вернет нам ответ с сервера, отправку самой формы предотвращаем в js’еКак же это аяксом отправляется, если в верстке в форме идет экшн?
action=»»
Я недопонимаю.
Спасибо большое за такой полезный пост!
Весь интернет перерыл, не нашел ни одного решения без плагинов, чуть с ума не сошел