Перейти к содержимому

Форма обратной связи - веб-форма, письма, свой обработчик

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

Решение

Ставим веб-форму на страницу:

$APPLICATION->IncludeComponent('bitrix:form.result.new', '', [
'WEB_FORM_ID' => 1, // идентификатор формы из настроек модуля
'USE_EXTENDED_ERRORS' => 'Y', // подробные сообщения об ошибках полей
'SEF_MODE' => 'N',
'CACHE_TIME' => 0, // форму не кэшируем: в ней живая сессия
]);

Поля рисует не шаблон компонента, а описание формы в настройках модуля. Добавить поле в разметку недостаточно: оно должно существовать в самой форме, иначе введённое значение никуда не сохранится и в письмо не попадёт.

Читаем результаты из кода:

use Bitrix\Main\Loader;
Loader::includeModule('form');
$res = CFormResult::GetList(1, ($by = 'ID'), ($order = 'DESC'), [], $isFiltered);
while ($result = $res->Fetch()) {
printf("%-6s %-20s %s\n",
$result['ID'], $result['DATE_CREATE'], $result['USER_AUTH'] ?: 'гость');
}

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

Проверяем, куда уходит письмо:

$res = CFormResult::GetList(1, ($by = 'ID'), ($order = 'DESC'), [], $f);
// шаблон письма и получатель настраиваются в почтовых событиях модуля почты
$events = CEventType::GetList(['TYPE_ID' => 'FORM_FILLING_FORM_1']);
while ($event = $events->Fetch()) {
printf("событие %s: %s\n", $event['EVENT_NAME'], $event['NAME']);
}

Каждая веб-форма создаёт при сохранении своё почтовое событие. Адрес получателя задаётся в шаблоне письма, а не в настройках формы, и жалобу «письмо не приходит» разбирают именно в шаблоне и в журнале отправки.

Добавляем свою проверку перед сохранением:

/local/php_interface/init.php
AddEventHandler('form', 'onBeforeResultAdd',
static function ($formId, &$fields) {
if ($formId == 1 && empty($fields['form_text_2'])) {
return false; // отклоняем результат: обязательное поле пустое
}
}
);

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

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

Своя форма нужна там, где сценарий выходит за рамки сбора заявок: данные уходят во внешнюю систему, ответ зависит от введённого, поля появляются по условию. Такую форму принимают контроллером и сохраняют своим кодом, а хранение и письма пишут руками - и именно этот объём работы веб-форма и экономит.

Типичные проблемы

Форма отправляется, письма нет.

Проблема в отправке почты, а не в форме. Результат при этом сохранён в базе, и заявка не потеряна.

Добавленное в шаблон поле не сохраняется.

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

Форма отправляется дважды.

Страница с формой закэширована вместе с ключом сессии. Форму выводят без кэширования компонента.

Проверка обходится пустым запросом.

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

Результаты есть, а в фильтре админки не находятся.

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

Частые вопросы

Как отправить копию письма клиенту?

Вторым почтовым событием со своим шаблоном и получателем из поля формы. Одно событие одному получателю - обычная схема.

Можно ли приложить файл к заявке?

Да, полем типа «файл» в описании формы. Файл сохраняется вместе с результатом, а в письмо попадает ссылкой.

Как показать форму без перезагрузки страницы?

Режимом обмена у компонента или своим запросом к контроллеру. Второй путь даёт полный контроль над разметкой и ответом.

Куда деваются результаты после удаления формы?

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

Смежное

Первоисточник