Создание формы обратной связи

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

Статья давно на сайте, но пришло время актуализировать ее, ведь с момента написания прошло более 5 лет, что-то устарело, за некоторые моменты откровенно стыдно, а что-то не так доходчиво разжевано.

С этого момента обновления статей буду делать максимально полными и подробными, чтобы вам не приходилось ничего искать на других ресурсах. Это статья, изначально, была ориентирована на форму с перебросом на страницу благодарности после нажатия кнопки «отправить».

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

Создание формы обратной связи – HTML разметка

Обычно? мне хватает двух-трех полей, так как нет смысла требовать от посетителя большего и раздражать его. Продажа, обычно, случается после разговора с консультантом или менеджером, а значит все детали можно узнать по телефону.

Больше на эту тему можно почитать в статье с вредными советами, которые помогут испортить ваш landing page.

Но, как и обещал, в этой статье мы сделаем практически все возможные варианты полей. Сначала просто получим имя, телефон и почту, а потом будем постепенно усложнять, добавляя текстовую область, чекбокс и прикрепление файла.

В большинстве случаев, для создания формы обратной связи я использую такую разметку:

<form class="contact-form" id="contact-form_1" method="POST" enctype="multipart/form-data">
  <p class="contact-form__title">Оставьте заявку на расчет стоимости</p>
  <p class="contact-form__description"></p>
  <div class="contact-form__input-wrapper">
    <input name="name" type="text" class="contact-form__input contact-form__input_name" placeholder="Введите ваше имя">
    <div class="contact-form__error contact-form__error_name"></div>
  </div>
            
  <div class="contact-form__input-wrapper">
    <input name="tel" type="tel" class="contact-form__input contact-form__input_tel" placeholder="Введите ваш телефон">
    <div class="contact-form__error contact-form__error_tel"></div>
  </div>

  <div class="contact-form__input-wrapper"> 
     <input name="email" type="email" class="contact-form__input contact-form__input_email" placeholder="Введите ваш email">
     <div class="contact-form__error contact-form__error_email"></div>
  </div>

  <button class="contact-form__button" type="submit"> Узнать стоимость </button>
</form>

Пример формы обратной связи

Знаю, что заголовок формы не согласован с кнопкой, но лень переделывать все скриншоты. Суть же не в этом совсем. Правда?

Давайте, кратко объясню, что тут к чему. В теге 'form' я размещаю два параграфа. В одном будет заголовок формы, а второй послужит для вывода сообщений и уведомлений, возникающих при отправке формы. Например, о том, что сообщение успешно отправлено в варианте, когда все происходит без перезагрузки.

Под каждым полем создаю 'div' для вывода уведомлений об ошибках при валидации '.contact-form__error'.

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

Далее, для простоты работы с js воспользуемся jQuery. Подключаем его, как обычно, перед всеми скриптами, которые зависят от него. Я, обычно, делаю это ближе к закрывающему тегу 'body', чтобы основной контент грузился быстрее.

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="/mail/js/mail.js"></script>

Скрипт 'mail.js' — это файл формы, который помогает в отправке и обработке ответа сервера. О нем чуть позже. Сейчас нужно познакомить вас со структурой всех файлов, отвечающих за отправку.

Структура проекта

Скрипт для отправки формы на почту

Здесь нас интересует папка 'mail'. Именно тут и происходит вся магия.

Обратите внимание, что она лежит в корне сайта.

В первую очередь давайте разберем файл 'config.php'. Тут задаются основные настройки формы.

Основные настройки формы

<?
	// *** Настройка обязательности полей, в случае если они присутствуют в вашей форме

	// Имя
	const NAMEISREQUIRED = true;
	const MSGSNAMEERROR = "Поле обязательно для заполнения";

	// Телефон
	const TELISREQUIRED = false;
	const MSGSTELERROR = "Поле обязательно для заполнения";

	// Email
	const EMAILISREQUIRED = false;
	const MSGSEMAILERROR = "Поле обязательно для заполнения";
	const MSGSEMAILINCORRECT = "Некорректный почтовый адрес";

	// Текстовое поле
	const TEXTISREQUIRED = false;
	const MSGSTEXTERROR = "Поле обязательно для заполнения";

	// Файл
	const FILEISREQUIRED = false;
	const MSGSFILEERROR = "Поле обязательно для заполнения";

	// Соглашение
	const AGGREMENTISREQUIRED = false;
	const MSGSAGGREMENTERROR = "Поле обязательно для заполнения"; 

	// Сообщение об успешной отправке
	const MSGSSUCCESS = "Сообщение успешно отправлено";

	// *** SMTP *** //

		require_once($_SERVER['DOCUMENT_ROOT'] . '/mail/phpmailer/smtp.php');
		const HOST = 'ssl://smtp.yandex.ru';
		const LOGIN = 'sender@yandex.ru';
		const PASS = 'senderPass';
		const PORT = '465';

	// *** /SMTP *** //

        // Почта с которой будет приходить письмо
	const SENDER = 'sender@yandex.ru';
	
	// Почта на которую будет приходить письмо
	const CATCHER = 'catcher@mail.ru';
	
	// Тема письма
	const SUBJECT = 'Заявка с сайта';
	
	// Кодировка
  const CHARSET = 'UTF-8';

В принципе я объясняю комментариями в коде что и зачем, константы имеют интуитивно понятные имена, но давайте для новичков объясню все еще подробнее.

В начале идут константы, которые отвечают за проверку обязательно ли поле или нет и какое сообщение будет выводится в случае ошибки. Например, константы для имени

const NAMEISREQUIRED = true;
const MSGSNAMEERROR = "Поле обязательно для заполнения";
  • 'const NAMEISREQUIRED = true;' — означает, что поле обязательно для заполнения. Если в вашем случае его можно не заполнять, то поставьте 'false'.
  • 'const MSGSNAMEERROR = «Поле обязательно для заполнения»;' — это сообщение, которое будет выводится пол полем, в случае если заполнение его обязательно, но по каким-то причинам пользователь этого не сделал.

То есть если имя обязательно, но не было заполнено, появиться сообщение 'Поле обязательно для заполнения'. Вот так:
Валидация формы

Далее идет константа с сообщением, которое увидит пользователь при успешной отправке, давайте, пока, реализуем такой функционал, а потом с перебросом на страницу благодарности.

 // Сообщение об успешной отправке
 const MSGSSUCCESS = "Сообщение успешно отправлено";

Можете вывести любое сообщение, которое подходит в вашем случае.

Теперь самое главное. Если прошлые вещи можно было оставить по умолчанию, то теперь нужно настроить отправку на почту. Так как в скрипте используется SMTP протокол передачи почты, то нужно узнать несколько параметров у вашего почтового сервиса. Это:

  • Адрес сервера — ( константа HOST )
  • Логин (адрес электронной почты) — ( константа LOGIN )
  • Пароль — ( константа PASS )
  • Порт — ( константа PORT )

пароль и логин у каждого свои, а 'HOST' и 'PORT' для популярных почтовых сервисов я приведу в списке.

Сервис HOST PORT
Яндекс ssl://smtp.yandex.ru 465
Gmail smtp.gmail.com 465
Mail.ru ssl://smtp.mail.ru 465

Будьте внимательны с этими параметрами, так как тут легко сделать ошибку и ничего приходить не будет.

С остальным все проще, объяснять по сути и нечего:

// Почта с которой будет приходить письмо
const SENDER = 'sender@yandex.ru';
	
// Почта на которую будет приходить письмо
const CATCHER = 'catcher@mail.ru';
	
// Тема письма
const SUBJECT = 'Заявка с сайта';
	
// Кодировка
const CHARSET = 'UTF-8';

Обратите внимание, что почта, указанная в 'const SENDER' должна совпадать с почтой, которую указали в 'LOGIN'.

Валидация формы перед отправкой

Я не стал очень сильно заморачиваться с валидацией, потому как всем, все равно, не угодишь и сделал валидацию на обязательность заполнения полей, а в случае с полем для ввода электронной почты то еще и на корректность ввода адреса.

Все вам понадобится дополнительная валидация, все это реализовано в файле 'valid.php'.

<?php
$msgs = [];
	if (isset($_POST['name']) ) {
        if(empty($_POST['name']) && NAMEISREQUIRED) {
            $msgs['name'] = MSGSNAMEERROR;
        } else {
            if (!empty($_POST['name'])) {
                $name = "<b>Имя: </b>" . trim(strip_tags($_POST['name'])) . "<br>";
            }
            
        }
    }

    if (isset($_POST['tel']) ) {
        if(empty($_POST['tel']) && TELISREQUIRED) {
            $msgs['tel'] = MSGSTELERROR;
        } else {
            if (!empty($_POST['tel'])) {
                $tel = "<b>Телефон: </b> " . trim(strip_tags($_POST['tel'])) . "<br>";
            }
        }
    }

    if (isset($_POST['email']) ) {
        if(empty($_POST['email']) && EMAILISREQUIRED) {
            $msgs['email'] = MSGSEMAILERROR;
        } else {
            if(!empty($_POST['email'])) {
                if (filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
                    $email = "<b>Почта: </b> " . trim(strip_tags($_POST['email'])) . "<br>";
                } else {
                    $msgs['email'] = MSGSEMAILINCORRECT;
                }
            }
        } 
    }
    
    if((empty($_POST['email']) && empty($_POST['tel'])) && (!EMAILISREQUIRED && !TELISREQUIRED)) {
        $msgs['attantion'] = 'Заполните хотя бы одно контактное поле для связи с вами';
    }

    if ($msgs) {
      echo json_encode($msgs);
      die;
    } else {
      $msgs['success'] = MSGSSUCCESS;
    }

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

if((empty($_POST['email']) && empty($_POST['tel'])) && (!EMAILISREQUIRED && !TELISREQUIRED)) {
 $msgs['attantion'] = 'Заполните хотя бы одно контактное поле для связи с вами';
}

Если вам это не нужно или у вас какой-то другой способ связи, поменяйте под свои нужды или удалите. Вот как это выглядит сейчас:

Форма обратной связи для лендинга

Отправка формы

Отправка формы осуществляется в файле mail.php, там нечего менять и настраивать. Оставьте как есть, если плохо разбираетесь в php. Если соберетесь добавить свои поля и, по какой-то причине не захотите скачать файл, предложенный мной ниже, где мы будем добавлять обещанный ранее функционал, то в тело письма, после валидации, необходимо передать переменные с данными полученными из формы. Делается это в 34 строке.

<?php

// mb_internal_encoding("UTF-8");
// ini_set('error_reporting', E_ALL);
// ini_set('display_errors', 1);
// ini_set('display_startup_errors', 1);

	use PHPMailer\PHPMailer\PHPMailer;
	if ($_SERVER["REQUEST_METHOD"] == "POST") {

		require_once($_SERVER['DOCUMENT_ROOT'] . '/mail/phpmailer/phpmailer.php');
		require_once($_SERVER['DOCUMENT_ROOT'] . '/mail/php/config.php');
		require_once($_SERVER['DOCUMENT_ROOT'] . '/mail/php/valid.php');

		if(defined('HOST') && HOST != '') {
			$mail = new PHPMailer;
			$mail->isSMTP();
			$mail->Host = HOST;
			$mail->SMTPAuth = true;
			$mail->Username = LOGIN;
			$mail->Password = PASS;
			$mail->SMTPSecure = 'ssl';
			$mail->Port = PORT;
			$mail->AddReplyTo(SENDER);
		} else {
			$mail = new PHPMailer;
		}

		$mail->setFrom(SENDER);
    $mail->addAddress(CATCHER);
    $mail->CharSet = CHARSET;
    $mail->isHTML(true);
		$mail->Subject = SUBJECT;
		$mail->Body = "$name $tel $email"; 
		if(!$mail->send()) {
    } else {
      echo json_encode($msgs);
    }
	
	} else{
          header ("Location: /"); // главная страница вашего лендинга
	}

Но еще раз напомню, что чуть ниже мы будем добавлять в форму и другие поля, а там изменяться и все эти файлы. Файлы phpmailer — это вспомогательная библиотека для правильной отправки данных на почту. Там ничего трогать нельзя.

Также, в отправке формы и валидацие участвует файл 'mail.js'. Именно он помогает реализовать отправку без перезагрузки страницы. Тут тоже ничего менять не нужно, если вы не планируете использовать страницу благодарности, а вам достаточно того, что уведомление об успешной отправке выводится в форме.

(function ($) {
$(".contact-form").submit(function (event) {
event.preventDefault();

	// Сохраняем в переменную form id текущей формы, на которой сработало событие submit
	let form = $('#' + $(this).attr('id'))[0];

	// Сохраняем в переменные дивы, в которые будем выводить текст ошибки
	let inpNameError = $(this).find('.contact-form__error_name');
	let inpEmailError = $(this).find('.contact-form__error_email');
	let inpTelError = $(this).find('.contact-form__error_tel');

	// Сохраняем в переменную див, в который будем выводить сообщение формы
	let formDescription = $(this).find('.contact-form__description');

	let fd = new FormData(form);
	$.ajax({
		url: "/mail/php/mail.php",
		type: "POST",
		data: fd,
		processData: false,
		contentType: false,
		success: function success(res) {
			let respond = $.parseJSON(res);

			if (respond.name) {
			 inpNameError.text(respond.name);
			} else {
			 inpNameError.text('');
			}

			if (respond.tel) {
				inpTelError.text(respond.tel);
			} else {
				inpTelError.text('');
			}

			if (respond.email) {
				inpEmailError.text(respond.email);
			} else {
				inpEmailError.text('');
			}

			if (respond.attantion) {
				formDescription.text(respond.attantion).css('color', '#e84a66').fadeIn();
			} else {
				formDescription.text('');
			}

			if (respond.success) {
				formDescription.text(respond.success).fadeIn();
				setTimeout(() => {
					formDescription.fadeOut("slow");
				}, 4000);
				setTimeout(() => {
					formDescription.text('');
				}, 5000);
			}
		},
	});
});
}(jQuery));

На этом, в принципе, с основной формой можно заканчивать. Дальше будут только «навороты».

Успешная отправка формы

Если что-то упустил или что-то непонятно — пишите в комментариях, попробую объяснить подробнее или дополнить статью.

Форма обратной связи с основными полями

Размер: 1.4 Мб

Стили специально не добавлял в статью, так как статья и так очень большая. В исходнике все есть.

Переброс на страницу благодарности

Как и говорил в начале статьи данная форма может работать как без перезагрузки, так и с перебросом на страницу благодарности. Давайте реализуем это. Нам понадобится немного подправить код в файле 'mail.js' и сама страница благодарности. На скриншоте со структурой проекта вы видели файл 'thank-you-page.php' — это и есть страница благодарности, которую я буду использовать. Как вы могли заметить, он лежит в корне. У вас она может быть где угодно, главное правильно указать к ней путь.

Итак, открываем файл 'mail.js', находим участок кода:

if (respond.success) {
   formDescription.text(respond.success).fadeIn();
   setTimeout(() => {
	formDescription.fadeOut("slow");
   }, 4000);
   setTimeout(() => {
	formDescription.text('');
   }, 5000);
}

И заменяем на:

if (respond.success) {
  window.location.replace("/thank-you-page.php?status=success"); 
}

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

Делать мы это будем при помощи php, поэтому убедитесь, что страница благодарности у вас сохранена именно в этом формате.

Если у вас уже страница в 'html', просто измените расширение. Это никак не повлияет на работоспособность.

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

<? if ($_GET['status'] == 'success') { ?>
<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>Страница благодарности формы обратной связи</title>
	<link rel="stylesheet" href="./css/style.css">
	<!-- <meta http-equiv="Refresh" content="4; URL=/"> -->
</head>

<body>
	<div class="thank-you-page">

		<h1 class="thank-you-page__title">Страница благодарности</h1>
		<p class="thank-you-page__descriptor">Оформляйте как вам будет угодно</p>
		<a class="thank-you-page__button" href="/">Вернуться на главную</a>

	</div>

</body>

</html>

<? } else {
    header ("Location: /"); // главная страница вашего лендинга
} ?>

В первой строке мы отлавливаем наш GET-параметр, и, если он совпадает с заданным, то показываем страницу, если нет, то перебрасываем пользователя на главную.

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

<meta http-equiv="Refresh" content="4; URL=/">

То есть это строка говорит, что через 4 секунды после открытия этой страницы, перекинь автоматически посетителя на главную страницу. За это время, человек успеет прочитать ваше сообщение и его благополучно вернет на главную.

Если вам важен такой функционал, то раскомментируйте ее и настройте приемлемое время.

Маска ввода номера телефона

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

Для маски ввода номера телефона нам понадобиться сторонний скрипт. Я предлагаю взять 'jQuery Mask Plugin' из статьи, ссылку на которую дал выше.

Подключаем после jQuery. Я делаю это так:

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- jQuery Mask Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.15/jquery.mask.min.js"></script>

<script src="/mail/js/mail.js"></script>

Теперь необходимо инициализировать скрипт.

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- jQuery Mask Plugin -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.15/jquery.mask.min.js"></script

<script src="/mail/js/mail.js"></script>
<script>
 $(function() {
  $('.contact-form__input_tel').mask('+3(000)000-00-00');
 });
</script>

После этого маска успешно появилась в поле телефона:

Маска ввода номера телефона

С этим, думаю, более-менее понятно. Теперь давайте потихоньку добавлять поля для ввода сообщения, чекбокс с принятием пользовательского соглашения и файла.

Совсем подробно расписывать не буду, просто покажу что и куда добавляю, а в конце дам ссылку на исходник. Если какое-то из полей вам не понадобится, то просто не используйте его в разметке, а в файле 'config' — установите значение 'false' там, где задаем обязательность заполнения.

Область для ввода сообщения

Конечно же многим из вас может понадобится поле для ввода сообщения. Для того, чтобы получить его мы воспользуемся тегом 'textarea'. Добавьте следующую разметку в форму:

<div class="contact-form__input-wrapper">
 <textarea name="text" class="contact-form__input contact-form__text" placeholder="Введите ваше сообщение"></textarea>
 <div class="contact-form__error contact-form__error_text"></div>
</div>

Стили я уже добавил в 'style.css', так что теперь наша форма выглядит так:

Добавление текстового поля

Теперь необходимо передать данные в файл валидации 'valid.php' и проверить все ли в порядке. Как уже говорил выше, у нас простейший случай с проверкой не пустое ли поле. Прежде чем перейти к реализации валидации давайте предположим, что поле для ввода текста обязательно для заполнения.

Для этого перейдем в файл 'config.php' и укажем 'true' в константе, отвечающей за это текстовое поле.

	// Текстовое поле
	const TEXTISREQUIRED = true;
	const MSGSTEXTERROR = "Поле обязательно для заполнения";

Теперь наше текстовое поле стало обязательно для заполнения. В файле 'valid.php', по аналогии с другими полями напишем такую проверку:

if (isset($_POST['text']) ) {
        if(empty($_POST['text']) && TEXTISREQUIRED) {
            $msgs['text'] = MSGSTEXTERROR;
        } else {
            if (!empty($_POST['text'])) {
                $text = "<b>Сообщение: </b> " . trim(strip_tags($_POST['text'])) . "<br>";
            }
        }
    }

Обратите внимание на 'text' в проверке POST запроса. Этот то самое значение, которое указывали в параметре 'name' у тега 'textarea'.

<textarea name="text" class="contact-form__input contact-form__text" placeholder="Введите ваше сообщение"></textarea>

В файле 'mail.js' сохраним 'div' в который будем выводить ошибку, если валидатор ее вернет для текстового поля:

// Сохраняем в переменные дивы, в которые будем выводить текст ошибки
let inpNameError = $(this).find('.contact-form__error_name');
let inpEmailError = $(this).find('.contact-form__error_email');
let inpTelError = $(this).find('.contact-form__error_tel');
let inpTextError = $(this).find('.contact-form__error_text');

А затем, ниже, напишем проверку:

if (respond.text) {
 inpTextError.text(respond.text);
} else {
 inpTelError.text('');
}

По аналогии вы можете добавлять любые другие поля. Но прежде нужно передать нашу переменную '$text' в тело письма. Делается это в файле 'mail.php' в 34 строке, той самой, о которой я уже упоминал выше.

$mail->Body = "$name $tel $email $text";

Теперь, если все сделали правильно, в письме будут приходить данные и из этого поля.

Проверка работоспособности формы

Еще раз повторюсь, если добавление этого поля показалось слишком сложным, то в конце статьи будет исходник, где можно просто в форме удалить лишнее инпуты, и все будет прекрасно работать.

Checkbox

Настало время добавить 'checkbox' с соглашением на обработку персональных данных. Вы можете делать и другие чекбоксы или радиокнопки. Принцип один и тот же для всех полей.

Создаем разметку в форме, определяем в 'config.php' обязательно ли поле, проверяем в валидаторе и формируем ошибку если она есть и выводим при помощи mail.js ее обратно в форму. Если нет, то передаем в mail.php и отправляем.

Итак, checkbox. Добавим разметку:

<div class="contact-form__input-wrapper">
<input type="checkbox" name="agreement" class="contact-form__input contact-form__checkbox" id="agreement" checked>
<label for="agreement" class="contact-form__checkbox-label">Я принимаю условия <a href="#">пользовательского соглашения</a></label>
<div class="contact-form__error contact-form__error_agreement"></div>
</div>

Не забудьте указать ссылку на соглашение. Стили уже добавлены в исходник.

Форма с чекбоксом

Идем в файл 'config.php' и делаем поле обязательным.

// Соглашение
const AGGREMENTISREQUIRED = true;
const MSGSAGGREMENTERROR = "Примите пользовательское соглашение";

Далее открываем файл 'valid.php' и добавляем следующий код:

    if(empty($_POST['agreement']) && AGGREMENTISREQUIRED) {
        $msgs['agreement'] = MSGSAGGREMENTERROR;
    } else {
        if (!empty($_POST['agreement'])) {
            $agreement = "<b>Соглашение: </b> Пользовательское соглашение принято " . "<br>";
        }
    }

Теперь переходим в файл 'mail.js' добавляем 'div' в который будет выводится ошибка, если она есть, и обработчик ошибки:

// Сохраняем в переменные дивы, в которые будем выводить текст ошибки
let inpNameError = $(this).find('.contact-form__error_name');
let inpEmailError = $(this).find('.contact-form__error_email');
let inpTelError = $(this).find('.contact-form__error_tel');
let inpTextError = $(this).find('.contact-form__error_text');

let inpAgreementError = $(this).find('.contact-form__error_agreement');

Обработчик ошибки:

if (respond.agreement) {
  inpAgreementError.text(respond.agreement);
} else {
  inpAgreementError.text('');
}

Осталось в тему письма добавить переменную с текстом о принятии соглашения.

$mail->Body = "$name $tel $email $text $agreement"; 

В принципе, если поле обязательно модно было этого и не делать, но пусть лучше будет.

Добавление файла

Многим может понадобиться возможность отправки файла, давайте реализуем и этот функционал. Я уже подготовил все, вам остается только добавить разметку и выбрать обязательное ли поле для заполнения.

Разметка:

<div class="contact-form__input-wrapper">
  <input class="contact-form__input contact-form__file" type="file" name="files[]">
  <div class="contact-form__error contact-form__error_file"></div>
</div>

Настройки в файле 'config.php':

	// Файл
	const FILEISREQUIRED = false;
	const MSGSFILEERROR = "&#x26a0; Забыли добавить файл";

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

Рабочая форма для сайта

А вот так выглядят пришедшие данные.

Данные из формы пришедшие на почту

Вот такая большая статья о создании формы обратной связи получилась.

Форма обратной связи с дополнительными полями

Размер: 1.4 Мб

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

Очистка полей после отправки данных формы на почту

Для того, чтобы очистить форму обратной связи после успешной отправки, нужно добавить несколько строк кода в файл «mail.js». Давайте сделаем это. В первую очередь сохраним в переменную класс формы на которой сработало событие «submit».

Чуть ниже, там где получали «id», добавим переменную «formClass» и передадим класс формы:

.
.
let form = $('#' + $(this).attr('id'))[0];

// Сохраняем в переменную класс формы
let formClass = $(this).attr('class');

// Сохраняем в переменные дивы, в которые будем выводить текст ошибки
let inpNameError = $(this).find('.contact-form__error_name');
.
.

А когда срабатывает событие success, при успешном ответе сервера, добавим саму очистку полей. Заменим это:

if (respond.success) {
   formDescription.text(respond.success).fadeIn();
   setTimeout(() => {
	formDescription.fadeOut("slow");
   }, 4000);
   setTimeout(() => {
	formDescription.text('');
   }, 5000);
}

На это:

if (respond.success) {
  formDescription.text(respond.success).fadeIn();
  $('.'+formClass).find('input').val('');
  $('.'+formClass).find('input').prop('checked', false);
  $('.'+formClass).find('textarea').val('');
    setTimeout(() => {
      formDescription.fadeOut("slow");
    }, 4000);
    setTimeout(() => {
      formDescription.text('');
    }, 5000);
}

Теперь, при успешной отправке, очистятся чекбоксы, обычные поля и textarea.

Автоматическое скачивание файла

Многие просили, чтобы я рассказал как в эту форму добавить возможность скачивания файла после отправки данных формы. Несмотря на то, что статья уже есть на блоге, просили добавить и в эту статью такую возможность. Давайте сделаем это.

Будем отталкиваться от того, что файл, который автоматически будет скачиваться после отправки формы, лежит в папке «files», которая, в свою очередь находится в корне вашего проекта.

Теперь, после успешной отправки нам необходимо добавить «Window.location» со ссылкой на расположение файла. Я предпочитаю делать это с небольшой задержкой, чтобы пользователь успел понять, что произошло, а именно увидеть сообщение об успешной отправке. Можно, конечно, и прелоадер «прикрутить», но это уже дело вкуса.

Напоминаю, что сигналом о том, что сообщение успешно отправлено у нас является строка пришедшая в файле «mail.js». Вот тут:

if (respond.success) {
//.
// some code
//.
}

Сюда и будем добавлять ссылку на файл. Поставим задержку в 1 секунду при помощи «setTimeout».

if (respond.success) {
 setTimeout(() => {
  window.location = '/files/test-file.docx';
 }, 1000);
}

Если вы работаете со страницей благодарности, то можно на нее поместить тот же код, например, просто в футере.

<script>
 window.onload = function() {
    setTimeout(() => {
     window.location = '/files/test-file.docx';
    }, 1000);
 };
</script>

Важно

Для корректной работы потребуется:

  • PHP > 7.
  • Сам сервер
  • Jquery 3 версии
  • Если тестируете на хостинге, то должен быть не тестовый период, не бесплатный домен и у хостера не отключена функция mail. Во всех этих случая хостер может накладывать ограничение на работоспособность под предлогом борьбы со спамом. Кроме того, некоторые хостеры не позволяют отправлять сообщения с почтовых адресов не привязанных к сайту.
  • Перед тем как задать вопрос, посмотрите нет ли ошибок в консоли и попробуйте вывести ошибки php.
  • Если не приходят сообщения, проверьте не попали ли письма в спам.
  • Если вам лень разбираться и самостоятельно делать форму, то рекомендую обратить внимание на конструкторы форм обратной связи

Как вам такой формат статей? Нужно ли делать настолько большие?

279 комментариев

  • dimadv7

    Здравствуйте. Рад слышать :) Ну конечно можно сдвинуть, но зависит же от стилей вашего сайта. В исходнике, выравнивание контейнера, в котором лежит форма происходит за счет

    margin: 0 auto;

    вот тут:

    #application {
        width: 475px;
        margin: 0 auto;
    }
    Ответить
  • Миша

    Спасибо, попробую сделать. Мы кстати земляки почти, если верить городу, который указан в контакте. Я сам из Донецка, но сейчас проживаю в Киеве. Так что можно дружить ;)

    Ответить
  • dimadv7

    В контакте правдивая информация. До этой долбаной АТО, котора давно уже просто ТО, учился и жил тоже в Донецке. Планировал оставаться там, но не сложилось пока… Конечно можем дружить )) Даже если и не земляки бы были ))

    Ответить
  • dimadv7

    А по форме, нужно убрать марин 0 авто. И двигать как душе угодно блок

    Ответить
  • Миша

    отлично, сначала сдвинулись только строчки, но потом допер, что нужно и саму форму (фон) тоже подправить. Вроде получилось, огромное тебе спасибо. В контакте сча добавлю в друзья, может даже поработаем вместе :)

    Ответить
  • Сергей

    Добрый день. Сделал все как было написано, но когда заполняю форму и нажимаю получить прайс, выскакивает окно с ошибкой и текстом
    Not Found
    The requested URL /application.php was not found on this server.
    Помогите что сделал не так. Делал на вордпрессе!

    Ответить
  • dimadv7

    Путь к файлу с обработчиком формы указан неправильно. Собственно это и написано :) Попробуй в корень покласть, там где wpconfig лежит

    Ответить
  • Юлия

    Здравствуйте, Дима. Скажите, пожалуйста, если на одной странице нужно поставить 8 форм для записи в разные группы с двумя одинаковыми полями (телефон и имя), нужно ли писать для каждой формы свой обработчик? Есть ли возможность как-то оформить в один, но чтобы на почту приходил заголовок каждый свой, смотря на какую кнопку (группу) нажал пользователь?

    Ответить
  • dimadv7

    Здравствуйте. Конечно можно один. Просто нужно добавить к каждой форме поле, у которого будет tipe=»hidden» (то есть оно будет невидимо для пользователя), а в параметре value написать нужный текст, например, заявка с шестой формы. А в обработчике принимать данные из этого поля, таким же образом, как и у других полей.

    Ответить
  • Евген

    Автор, ты крут. Я очень долго сношал свой мозг с этой формой оплаты. Оказывается все намного проще. Простое Человеческое тебе спасибо)

    Ответить
  • dimadv7

    Ах-ха. Спасибо за отзыв)

    Ответить
  • Юлия

    не получается и все тут. Приходит на почту, но значение поля hidden почему-то одно и тоже! Всю голову сломала. .. Помогите, пожалуйста

    Расписание занятий

    С посещением 1 раз в неделю!
    вечер ВТ 18:00-23:00

    Записаться

    вечер ЧТ 18:00-23:00

    Записаться

    вечер (ПН,ПТ) 18:00-23:00

    Записаться

    вечер (ВТ,ЧТ) 18:00-23:00

    Записаться

    СР 18:00-21:30, СБ 14:30-18:00

    Записаться

    вых (СБ,ВС) 9:00-14:15

    Записаться

    утро (ВТ,ЧТ) 9:00-14:15

    Записаться

    Записаться на ближайшую дату

    Код обработчика:
    <?php
    $sendto = "адрес@ящика"; // почта, на которую будет приходить письмо
    $username = $_POST['name']; // сохраняем в переменную данные полученные из поля c именем
    $usertel = $_POST['telephone']; // сохраняем в переменную данные полученные из поля c телефонным номером
    $usermail = $_POST['email']; // сохраняем в переменную данные полученные из поля c адресом электронной почты
    $tema = $_POST['named']; // тема письма

    // Формирование заголовка письма
    $subject = "Новое сообщение";
    $headers = "From: " . strip_tags($usermail) . "\r\n";
    $headers .= "Reply-To: ". strip_tags($usermail) . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html;charset=utf-8 \r\n";
    // Формирование тела письма
    $msg = "»;
    $msg .= «Cообщение с сайта «.$tema.»\r\n»;
    $msg .= «От кого: «.$username.»\r\n»;
    $msg .= «Почта: «.$usermail.»\r\n»;
    $msg .= «Телефон: «.$usertel.»\r\n»;
    $msg .= «»;

    // отправка сообщения
    if(@mail($sendto, $subject, $msg, $headers)) {
    echo «Ваша заявка успешно отправлена. «;
    } else {
    echo «Ошибка. Напишите нам на почту «;
    }
    ?>

    Ответить
  • Юлия

    Уй, как-то вставилось не html <!— Расписание занятий

    С посещением 1 раз в неделю!
    вечер ВТ 18:00-23:00

    Записаться

    вечер ЧТ 18:00-23:00

    Записаться

    —>

    Ответить
  • dimadv7

    Вордпрес режет код. Не нужно его вставлять в комментарии. Вы же поменяли id у формы? У каждой формы должен быть свой. И у каждой кнопки значение атрибута form должно соответствовать айдишнику формы. Если не получится, напишите мне в ВК. Попробуем разобраться.

    Ответить
  • Юлия

    Все решено. Терпение + внимательность + чистка кэша)) Спасибо еще раз за помощь!

    Ответить
  • Валентин Левченко

    Очень классная форма — и все прекрасно работает. Только письма почему-то приходят с неправильной кодировкой…От кого: Валентин Левченко

    Как это можно исправить?

    Ответить
  • dimadv7

    Скорее всего у вас не UTF-8 прописана. Нужно в явном виде указать на страницах,

    <meta charset="utf-8"/>

    . Кроме этого, нужно сохранять все файлы в utf-8 без бом. Если это не поможет, то нужно в файле htaccess прописать AddDefaultCharset UTF-8. Если и это не поможет , то, возможно, на сервере есть файл php.ini. В нем нужно внести правки и указать кодировку. Возможен вариант, что у вас сайт весь в windows-1251, тогда, просто поменяйте кодировку на странице обработчика формы, между тегами head, на свою и замените в строке

    $headers .= "Content-Type: text/html;charset=utf-8 \r\n";

    c utf на свою.

    Ответить
  • Алексей

    А вы не могли бы написать статью, как встроить подобную форму в плагин для wordpress, который называется optimizepress? Был бы очень признателен!

    Ответить
  • dimadv7

    Здравствуйте, я не занимаюсь написанием плагинов для wordpress

    Ответить
  • Рома

    Не работает:(
    Попробывал другой какой-то буржуйский скрипт, он работает.
    Но хотелось установить ваш. Здесь проще…

    Ответить
  • Рома

    Конкретно не отсылает письма, хотя пишет, что успешно отправлено. Качал готовую версию вашего скрипта.

    Ответить
  • dimadv7

    С mail.ru не дружит скрипт, не нравиться ему, как составлен заголовок и тело скрипта. Но пользователи mail.ru, как и пользователи IE — должны страдать)) Попробуй просто почту от Яндекса, например, или gmail, но в gmail, первый раз, может в спам кинуть, нужно будет один раз указать, что это не спам и все будет прекрасно работать.

    Ответить
  • Борис

    Добрый день! Поставил форму, данные отправляет, но на почту ничего не приходит. Я добавил дополнительное поле «Город». В чем может быть проблема?
    Вот php-код:

    <?php

    $sendto = "krooto@mail.ru"; // почта, на которую будет приходить письмо
    $username = $_POST['name']; // сохраняем в переменную данные полученные из поля c именем
    $usermail = $_POST['email']; // сохраняем в переменную данные полученные из поля c адресом электронной почты
    $usertel = $_POST['telephone']; // сохраняем в переменную данные полученные из поля c телефонным номером
    $usercity = $_POST['city']; // сохраняем в переменную данные полученные из поля c городом

    // Формирование заголовка письма
    $subject = "Новое сообщение";
    $headers = "From: " . strip_tags($usermail) . "\r\n";
    $headers .= "Reply-To: ". strip_tags($usermail) . "\r\n";
    $headers .= "MIME-Version: 1.0\r\n";
    $headers .= "Content-Type: text/html;charset=utf-8 \r\n";

    // Формирование тела письма
    $msg = "»;
    $msg .= «Cообщение с сайта\r\n»;
    $msg .= «От кого: «.$username.»\r\n»;
    $msg .= «Почта: «.$usermail.»\r\n»;
    $msg .= «Телефон: «.$usertel.»\r\n»;
    $msg .= «Город: «.$usercity.»\r\n»;
    $msg .= «»;

    // отправка сообщения
    if(@mail($sendto, $subject, $msg, $headers)) {
    echo «»;
    } else {
    echo «»;
    }

    ?>

    Ответить
  • Ян

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

    Ответить
  • dimadv7

    Да. Переверстать под себя форму и задать все не в пикселях, а в относительных единицах.

    Ответить
  • Диана

    Доброго времени суток!
    Спасибо большое за статью, очень помогла!
    Но почему-то вместо слов от кого, телефон, почта стоят вот такие знаки ����� . Как можно это исправить?

    Ответить
  • dimadv7

    Нужно привести все файлы к одной кодировки. Например utf-8. То есть сохранить все файлы в utf-8 и явно указать ее в доктайпе. Кроме того, если есть файл .htaccess, то и там указать utf-8

    Ответить
  • Михаил

    ПОМОГИТЕ!
    Подскажите где написать свои ЕМАИЛ чтобы письма приходили мне на почту?
    Вот форма html
    Жду звонка

    Ответить
  • Илья

    Привет!
    Подскажите, как сделать так, чтобы тема письма совпадала с Titile страницы на которой была заполнена форма. Так как страницы разные, а форма типовая.

    Заранее спасибо за ответ, с ув. Илья

    Ответить
  • dimadv7

    Можно создать у формы скрытое текстовое поле с type=»hidden», и в значение в value вписать то, что находиться в title, а в обработчике ловить данные точно так же, как и данные из других полей. То есть в $subject вывести не текст а то, что вытащили из скрытого поля, то есть title

    Ответить
  • Илья

    Спасибо да я так, вчера и решил эту проблему. Спасибо за ответ

    Ответить
  • Егор

    Как-то сложно это все, к тому же на сервере должна быть поддержка PHP. Я для себя сделал выбор в пользу онлайн генераторов форм. К счастью их сейчас огромное множество. Мне вот нравится вот этот — formdesigner.ru. Довольно неплохой сервис, плюс есть интеграция с сервисами email рассылок и CRM системами. Очень удобно. Кому лень разбираться с php кодом рекомендую попробовать какой-то онлайн сервив.

    Ответить
  • dimadv7

    Здравствуйте, точно. Я тоже когда-то пользовался. Просил клиент установить. Нужно будет статью написать. Спасибо, что напомнили)

    Ответить
  • Алексей

    Всё это хорошо. Но как быть с обработкой данных с апселла?
    Добрый вечер. Неделю уже карплю с товарным одностраничником.

    Подскажите пожалуйста, как мне получить данные с 2 кнопок и прибавить их к уже полученным данным на главной странице index.php, где находится форма всего с 2 полями? Скрипт лежит в файле send.php, обрабатывает и отправляет на мыло данные полей и в конце перебрасывает посетителя на upsell.php, где и находятся эти кнопки.

    А мне нужно, как-то собранные данные с полей формы не отправлять, а сначала получить данные с тех 2 кнопок, что в файле upsell.php (в зависимости какую кнопку нажмёт покупатель), а уже потом, прибавив одно из значений всё это отправить одним сообщением на мыло.

    Дошёл лишь до момента, когда собраны данные с полей формы, нажата кнопка «Заказать» и данные улетают на мыло , одновременно с переходом на страницу upsell.php

    Ответить
  • dimadv7

    Здравствуйте, посмотрите в сторону сессий и cookies.

    Ответить
  • Алексей

    Здравствуйте. Где посмотреть: здесь на форуме или у себя в браузере?

    Ответить
  • dimadv7

    Нет, на блоге об этом ничего нет. В документации по php, например. Суть в том, что можно сохранить данные в сессии и использовать их на любой странице, пока она открыта.

    Ответить
  • Сергей

    Спасибо за форму! У меня такой вопрос, вставил форму сделал тестовый заказ, но сообщение об успешной отправке заявки открывается не в новом окне а там же встроенным _http://leadoffer.ru/test1/order.htm

    Ответить
  • Chupacabra

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

    Ответить
  • Вика

    Большое спасибо за детальное описание формы! Правда поскольку впервые разбираюсь в этом моменте, естественно не все получилось((( Помоги, плиз, разобраться! При отправке формы выдает такой текст:
    Not Found

    The requested URL /application.php was not found on this server.

    Что это может значить?

    Ответить
  • dimadv7

    Что путь к обработчику формы неправильно прописан. В форме он указывается в атрибуте action. При попытке передать данные по заданному пути нет файла application.php. Это и есть обработчик

    Ответить
  • dimadv7

    Если все осталось как в исходнике, то файл application.php должен в корне сайта лежать

    Ответить
  • Вика

    Сорри! Нашла ошибку)) Порядок теперь)) Все прекрасненько работает! =))) Еще раз спасибо тебе!

    Ответить
  • Вика

    Приветик)) а как застайлить приходящие на почту данные? Чтоб они не просто строкой были, а допустим, каждое с новой строки, «имя» жирным шрифтом, в таком духе? А то пока так http://prntscr.com/auxpfm

    Ответить
  • dimadv7

    В статье и так все с новой строки , и имя жирным… Там прописаны теги < p > и < strong >

    $msg .= "<h2 style='font-weight:bold;border-bottom:1px dotted #ccc;'>Cообщение с сайта</h2>\r\n";
    $msg .= "<p><strong>От кого:</strong> ".$username."</p>\r\n";
    $msg .= "<p><strong>Почта:</strong> ".$usermail."</p>\r\n";
    $msg .= "<p><strong>Сайт:</strong> ".$usertel."</p>\r\n";
    
    Ответить
  • Евгений

    Спасибо. Все доходчиво, просто и красиво.

    Ответить
  • Артур

    Может кто сталкивался с такой проблемой. Перестали работать формы заявок на сайте. Выдает такую ошибку » Ошибка скрипта send.php» Хотя на другом хостинге копия этого сайта работает без проблем.

    Ответить
  • Евгения

    А версии php одинаковые? Может в этом проблема, хотя, должно работать и на более ранних. Вообще, не понятная ошибка, должно быть на английском написано.

    Ответить
  • YG

    Напишите, пожалуйста, как сделать форму в модальном окне с автоматическим закрытием после отправки формы либо переброску на страницу благодарности. Если можно еще реализовать проверку формы на правильность заполнения (чтобы в поле ввода номера телефона нельзя было ввести буквы). Спасибо!

    Ответить
  • Дима

    Здравствуйте!
    Подскажите пожалуйста как добавить две или три такие формы на один ленгдинг?
    Что нужно изменить в коде? Я новичек в том деле и не очень понимаю.

    Ответить

Добавить комментарий

 

Подписывайтесь на обновления, чтобы ничего не пропустить.