В этой статье рассмотрим, как создать форму обратной связи для сайта, используя HTML, Bootstrap, JavaScript (jQuery) и PHP.

Особенности контактной формы: работа без перезагрузки страницы (ajax), наличие защиты (капчи), защита от XSS атак (очистка полей с помощью php фильтров), возможность прикрепления к ней файлов, отправка данных на почту (отправленные файлы приходят на почту посредством вложений).

Что такое форма обратной связи?

Форма обратной связи (контактная форма, feedback form, contact form) - это HTML-форма для сайта, посредством которой администратор или менеджер сайта может получать данные от пользователей. Другими словами это один из способов, с помощью которого одни пользователи (посетители сайта) могут взаимодействовать с другими пользователями (менеджерами или администраторами сайта).

Как скачать форму обратной связи?

Ajax форма обратной связи с капчей и возможностью прикрепления к ней файлов находится на GitHub.

Посмотреть проект feedback-form на Github

Также её можно скачать с Яндекс хранилища:

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

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

Внешний вид формы обратной связи
Внешний вид формы обратной связи
Как осуществляется валидация формы обратной связи
Как осуществляется валидация формы обратной связи
Отображение информации об успешной отправки формы обратной связи
Отображение информации об успешной отправки формы обратной связи

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

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

Форму обратной связи, работающей без перезагрузки страницы, структурно можно представить в виде следующей схемы:

Структурная схема формы обратной связи c AJAX
Структурная схема формы обратной связи c AJAX

Из схемы видно, что форма обратной связи состоит из 2 основных частей: клиентской и серверной.

Клиентская часть формы обратной связи состоит из следующих файлов:

  • index.html - веб-страница, содержащая html5 форму обратной связи;
  • main.js - JavaScript сценарий, который подключен к странице index.html);
  • bootstrap.min.css, bootstrap.min.js - CSS стили и JavaScript плагин Bootstrap;
  • jquery.jgrowl.min.css, jquery.jgrowl.min.js - CSS стили и jQuery-плагин для отображения всплывающих сообщений;
  • jquery-3.2.1.min.js - библиотека jQuery, необходимая для работы js-плагина Bootstrap, jGrowl и скрипта main.js;
  • glyphicons-halflings-regular.eot и др. - файлы, содержащие иконки.
Файловая структура клиентской части формы обратной связи
Клиентская часть формы обратной связи

В качестве примера, рассмотрим HTML форму, состоящую из:

  • 3 полей (имя, email-адреса и сообщения);
  • блока, содержащего элементы input с type="file" (для прикрепления файлов к HTML форме);
  • капчи (защита формы от спама);
  • чекбокса, для принятия условий пользовательского соглашения;
  • кнопки, отправляющей её на сервер.

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

Сценарий JavaScript (main.js) используется для отправки контактной формы на сервер посредством технологии AJAX (т.е. без перезагрузки страницы). Но кроме отправки, js-сценарий выполняет ещё следующие вспомогательные операции:

  • проверку полей формы на корректность их заполнения (валидацию). Данное действие выполняется с помощью HTML5 функции checkValidity.
  • отображение ошибок валидации (с помощью окрашивания соответствующих полей формы в красный цвет) и отображения всплывающих сообщений;
  • вывод в блоке (в котором пользователь осуществляет прикрепление файлов к форме) информации о количестве файлов, сообщения о соответствии выбранных файлов установленным критериям, а также для добавления новых элементов input с type="file";
  • обновление кода капчи (получение нового изображения с сервера);
  • получение ответа от сервера и его отображение на странице.

Подготовку данных формы для отправки осуществляется на базе HTML5 объекта FormData. Информация, собранная с помощью FormData отправляется на сервер посредством метода POST.

Серверная часть формы обратной связи состоит из следующих файлов:

  • captcha.php - скрипт для генерации капчи;
  • oswald.ttf - шрифт, с помощью которого код капчи пишется на изображении;
  • background.png - изображение, на которое будет наложен текст капчи;
  • process.php - скрипт, выполняющий: валидацию данных формы; отправку данных на email и запись их в текстовый файл; формирование ответа в формате JSON;
  • process_settings.php - содержит переменные и константы, с помощью которых осуществляется настройка process.php;
  • PHPMailerAutoload.php - автозагрузчик библиотеки PHPMailer.
Файловая структура серверной части формы обратной связи
Серверная часть формы обратной связи

PHP скрипт process.php выполняет следующие функции:

  • проверяет метод запроса, а также как он послан (с помощью AJAX или нет);
  • выполняет очистку (фильтрацию) данных (для защиты от XSS);
  • выполняет проверку (валидацию) полей формы;
  • проверяет правильность введённого пользователем кода капчи;
  • проверяет, соответствуют ли полученные файлы установленным характеристикам;
  • перемещает файлы, отправленные пользователем, под уникальными именами в заданную директорию на сервере;
  • в случае успешного выполнения всех вышеприведённых действий отправляет письмо (email) с вложениями по указанному адресу. Кроме отправки письма он также сохраняет данные формы в текстовый файл;
  • отправляет клиенту (браузеру пользователя) результат (ответ) в формате JSON, содержащий сведения об успехе или возникшие при обработке формы ошибки.

Файлы формы обратной связи имеют кодировку UTF-8 без BOM.

Для проверки работоспособности формы в Денвере необходимо в корне сайта создать файл .htaccess и добавить в него строчку: AddDefaultCharset UTF-8.

Установка и настройка формы обратной связи

Установка формы обратной связи на сервер осуществляется путём копирования папки feedback в корневую директорию сайта.

После копирования контактная форма на сайте с доменным именем sitename.ru будет доступна адресу http://sitename.ru/feedback/ или https://sitename.ru/feedback/ в зависимости от используемого протокола.

Основные действия по настройке формы:

  1. Определиться с полями формы (файл index.html). При необходимости добавить новые поля или удалить существующие.
  2. Изменить настройки инициализации формы в файле main.js.
  3. Изменить переменные и константы в файле process_settings.php.
  4. При изменении полей HTML формы внести коррективы в файл process.php.
  5. Поправить файл email.tpl (шаблон email письма). Если вы отправляете информационное письмо клиенту об успешной отправке сообщения, то необходимо отредактировать и файл email_client.tpl.

Указание обработчика HTML форме осуществляется с помощью атрибута action:

<form id="feedbackForm" action="/feedback/process-feedback-form.php" enctype="multipart/form-data" novalidate>
  ...
</form>

Настройка файла main.js

Настройка JavaScript кода осуществляется посредством создания экземпляра объекта ProcessForm и указания ему необходимых параметров:

// feedbackForm - id обрабатываемой HTML-формы (основной параметр)
var formFeedback = new ProcessForm({idForm:'feedbackForm'});
formFeedback.init();

Более детальная настройка JavaScript сценария для обработки той или иной формы осуществляется посредством указания дополнительных ключей:

/*
Параметры указываются в виде:
{
ключ: значение;
ключ: значение;
...
}
idForm - id формы обратной связи (по умолчанию feedbackForm)
existenceUploadsFile - наличие у формы блока загрузки файлов (по умолчанию true)
countFiles - количество файлов для загрузки (по умолчанию 5)
maxSizeFile - максиальный размер файла в байтах (по умолчанию 524288 байт)
validFileExtensions - допустимые расширения файлов (по умолчанию 'jpg','jpeg','bmp','gif','png')
existenceCaptcha - наличие у формы капчи (по умолчанию true)
hideForm - скрыть форму после отправки данных
agreeCheckbox - флажок о принятии пользовательского соглашения перед отправкой формы (по умолчанию true)
*/

С помощью функции-конструктора ProcessForm можно обрабатывать любое количество форм. Осуществляется это следующим образом:

// feedbackForm - id первой HTML-формы
var formFeedback = new ProcessForm({idForm:'feedbackForm'});
formFeedback.init();
// contactForm - id второй HTML-формы 
var contactForm = new ProcessForm({idForm:'contactForm'});
contactForm.init();

Ошибки валидации сценарий JavaScript отображает посредством всплывающих сообщений jGrowl. При формировании текста ошибки имя поля берётся из содержимого элемента label, а текст ошибки из свойства элемента validationMessage.

Файл process_settings.php (настройки для process.php)

Файл process_settings.php содержит некоторые константы и переменные, которые используются файлом process.php для валидации файлов формы и отправки email:

// максимальный размер файла 512Кбайт (512*1024=524288)
const MAX_FILE_SIZE = 524288;
// директория для хранения загруженных файлов
$uploadPath = dirname(dirname(__FILE__)) . '/uploads/';
// разрешённые расширения файлов
$allowedExtensions = array('gif', 'jpg', 'png');

// от какого email будет отправляться письмо
const MAIL_FROM = 'no-reply@mydomain.ru';
// от какого имени будет отправляться письмо
const MAIL_FROM_NAME = 'Имя_сайта';
// тема письма
const MAIL_SUBJECT = 'Сообщение с формы обратной связи';
// кому необходимо отправить письмо
const MAIL_ADDRESS = 'manager@mydomain.ru';

// настройки mail для информирования пользователя о доставке сообщения
const MAIL_SUBJECT_CLIENT = 'Ваше сообщение доставлено';

Как формируется результат в process.php

Формирование результата обработки формы на стороне сервера (по умолчанию process.php) осуществляется с помощью переменной $data.

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

  • success - успешная обработка формы на сервере.
  • error - возникла ошибка при проверке формы.

Создание сообщения, содержащей подробную информацию об ошибке осуществляется с помощью этой же переменной ($data), но имеющей в качестве ключа имя HTML элемента:

Например, формирование ошибки для поля email:

$data['email'] = 'Поле <b>Email</b>  имеет не корректный адрес';

Создание информационных сообщений осуществляется с помощью ключа info:

$data['info'][] = 'Одно сообщение';
$data['info'][] = 'Ещё одно сообщение';

Как осуществляется добавление файлов в письмо

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

Код php, добавляющий в тело письма ссылки на файлы:

// добавление файлов в виде ссылок
if (isset($attachments)) {
    $listFiles = '<ul>';
    foreach ($attachments as $attachment) {
        $fileHref = substr($attachment, strpos($attachment, 'feedback/uploads/'));
        $fileName = basename($fileHref);
        $listFiles .= '<li><a href="' . $startPath . $fileHref . '">' . $fileName . '</a></li>';
    }
    $listFiles .= '</ul>';
    $bodyMail = str_replace('%email.attachments%', $listFiles, $bodyMail);
} else {
    $bodyMail = str_replace('%email.attachments%', '-', $bodyMail);
}

В email шаблоне место, в которое будут вставлены ссылки, определяется плейсхолдером %email.attachments%:

Файлы:<br>
%email.attachments%

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

Прикрепление файлов к email письму в process.php осуществляется следующим образом:

// прикрепление файлов к письму
if (isset($attachments)) {
    foreach ($attachments as $attachment) {
        $mail->addAttachment($attachment);
    }
}

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

Кроме отправки формы на email, php-скрипт process.php также осуществляет добавление отправленных данных в файл.

// отправка данных формы в файл
if ($data['result'] == 'success') {
    $name = isset($name) ? $name : '-';
    $email = isset($email) ? $email : '-';
    $message = isset($message) ? $message : '-';
    $output = "---------------------------------" . "\n";
    $output .= date("d-m-Y H:i:s") . "\n";
    $output .= "Имя пользователя: " . $name . "\n";
    $output .= "Адрес email: " . $email . "\n";
    $output .= "Сообщение: " . $message . "\n";
    if (isset($attachments)) {
        $output .= "Файлы: " . "\n";
        foreach ($attachments as $attachment) {
            $output .= $attachment . "\n";
        }
    }
    if (!file_put_contents(dirname(dirname(__FILE__)) . '/info/message.txt', $output, FILE_APPEND | LOCK_EX)) {
        $data['result'] = 'error';
    }
}

Как убрать капчу из формы обратной связи

Если вам не нужна капча, то необходимо:

1. Удалить из HTML формы блок капча:

<!-- Капча -->
<div class="captcha">
    <img class="img-captcha" src="/feedback/captcha/captcha.php"
         data-src="/feedback/captcha/captcha.php">
    <div class="btn btn-default refresh-captcha"><i class="glyphicon glyphicon-refresh"></i>
        Обновить
    </div>
    <div class="form-group has-feedback" style="margin-top: 10px;">
        <label for="captcha" class="control-label">Код, показанный на изображении</label>
        <input type="text" name="captcha" maxlength="6" required="required" id="captcha"
               class="form-control captcha" placeholder="******" autocomplete="off" value="">
        <span class="glyphicon form-control-feedback"></span>
    </div>
</div>

2. Установить при создании экземпляра объекта ProcessForm ключ existenceCaptcha со значением false:

var contactForm = new ProcessForm({
  idForm:'contactForm',
  existenceCaptcha: false
});
contactForm.init();

3. В php обработчике формы (по умолчанию process.php) удалить блок, в котором осуществляется валидация капчи:

//валидация капчи
if (isset($_POST['captcha']) && isset($_SESSION['code'])) {
    $captcha = filter_var($_POST['captcha'], FILTER_SANITIZE_STRING); // защита от XSS
    if ($_SESSION["code"] != $captcha) { // проверка капчи
        $data['captcha'] = 'Вы неправильно ввели код с картинки';
        $data['result'] = 'error';
    }
} else {
    $data['captcha'] = 'Произошла ошибка при проверке проверочного кода';
    $data['result'] = 'error';
}

Как добавить в форму новое поле

Например, для того чтобы добавить номер телефона в форму обратной связи необходимо выполнить следующие действия:

1. Добавить элемент input для ввода телефона в HTML форму (файл index.html):

<!-- Телефон пользователя -->
<div class="form-group has-feedback">
  <label for="phone" class="control-label">Телефон</label>
  <input type="text" name="phone" class="form-control" value="" maxlength="16" placeholder="Телефон">
  <span class="glyphicon form-control-feedback"></span>
</div>

2. При необходимости создать маску для ввода телефона в поле input (файл index.html):

<!-- Необходимо вставить после подключения библиотеки jQuery -->  
  
<!-- Скрипт для создания масок (https://github.com/igorescobar/jQuery-Mask-Plugin) -->
<script src="/feedback/vendors/mask/jquery.mask.min.js"></script>
<!-- Добавление маски к полю с атрибутом name -->
<script>
  $(function() {
    $('[name="phone"]').mask("+7(000)000-00-00", {
      clearIfNotMatch: true,
      placeholder: "+7(___)___-__-__"
    });
    $('[name="phone"]').focus(function(e) {
      if ($('[name="phone"]').val().length == 0) {
        $(this).val('+7(');
      }
    })
  });
</script>

3. Вставить в process.php код для валидации телефона:

//валидация поля phone
if (!empty($_POST['phone'])) {
    $phone = preg_replace('/\D/', '', $_POST['phone']); //получить номер телефона (цифры) из строки
    if (!preg_match('/^(8|7)(\d{10})$/', $phone)) {
      $data['phone'] = 'Поле Телефон содержит не корректный номер!';
      $data['result'] = 'error';
    }
}

4. Вставить строчку в process.php, которая будет заменять плейсхолдер %email.phone% в содержимом файла email.tpl на значение переменной $phone или на строку "не указан":

$bodyMail = str_replace('%email.phone%', isset($phone) ? $phone : 'не указан', $bodyMail);

5. Если вы используете отправку данных в файл, то добавьте ещё следующее в файл process.php:

$phone = isset($phone) ? $phone : '-';
// ...
$output .= "Телефон: " . $phone . "\n";

6. Добавить плейсхолдер %email.phone% в необходимое место в файл email.tpl:

Телефон пользователя: <b>%email.phone%</b><br>

Статьи, похожие на данную тему: