MODX. Создание и обработка форм с использованием FormIt
Отредактировано: 20 Февраля 2019
FormIt — компонент который обрабатывает поля формы после нажатия кнопки «Отправить». Не стоит расценивать его как компонент которым можно создавать форму, это лишь помощник в настройке уже подготовленной формы, избавляющий от написания своих PHP скриптов.
У FormIt есть Хуки (Hooks) — скрипты, которые выполняются во время обработки. Хуки могут быть линейными, т.е. выполняются по очереди, а могут быть последовательными, т.е. если выполнено условие первого хука, то начнется выполнение следующего хука.
Существуют также Прехуки (Pre-Hooks), скрипты, которые выполняются до загрузки формы. К примеру скрипт который устанавливает значение по умолчанию для полей форм в старых браузерах, которые не поддерживают соответствующие html плейсхолдеры.
Можно создавать собственные хуки и прехуки указывая их в параметрах preHook и hook FormIt. Стоит учитывать, что они будут выполняться в порядке указанном при вызове, поэтому, если один из скриптов выдал ошибку, сломаются и последующие.
Подключение простой формы с использованием FormIt
Код полностью
[<!--code-->[!FormIt?
&hooks=`email`
&emailFrom=`donotreply[@]yourdomain.com`
&emailTpl=`mailtpl.feedback`
&emailTo=`donotreply@yourdomain.com, admin@yourdomain.com`
&emailSubject=`Письмо с сайта yourdomain.com`
&successMessage=`Сообщение отправлено`
&validate=`name:required,
email:email:required,
comment:required,
antispam:blank`
]]
<form action="" method="post">
<label for="name">Name:</label>
<input type="text" name="name" id="name" value="[<!--code-->[!+fi.name]]">
<label for="email">Email</label>
<input type="text" name="email" id="email" value="[<!--code-->[!+fi.email]]">
<label for="comment">Comment</label>
<textarea name="comment" id="comment" cols="30" rows="10" value="[<!--code-->[!+fi.comment]]"></textarea>
<input type="text" name="antispam" id="antispam" value="">
<input type="submit" value="Submit">
</form>
[[!+fi.validation_error_message:!empty=`
<div class="alert">
<h3>Пожалуйста, исправьте следующие ошибки:</h3>
<ul>
[[!+fi.error.name:!empty=`<li><a href="blog/web/back-end/modx/formit/#name">Поле «Имя» не заполнено</a></li>`]]
[[!+fi.error.email:!empty=`<li><a href="blog/web/back-end/modx/formit/#email">Поле «Email» не заполнено</a></li>`]]
[[!+fi.error.comment:!empty=`<li><a href="blog/web/back-end/modx/formit/#comment">Поле «Комментарий» не заполнено</a></li>`]]
</ul>
</div>`]]
- В нужном месте шаблона, или на отдельной странице создадим html код формы
-
<form action="" method="post"> <label for="name">Имя:</label> <input type="text" name="name" id="name" > <label for="email">Email</label> <input type="text" name="email" id="email" > <label for="comment">Комментарий</label> <textarea name="comment" id="comment" cols="30" rows="10"></textarea> <input type="submit" value="Submit"> </form>
Добавим некешируемые плейсхолдеры FormIt ([[!+fi.код_поля]])
<form action="" method="post"> <label for="name">Name:</label> <input type="text" name="name" id="name" value="[[!+fi.name]]"> <label for="email">Email</label> <input type="text" name="email" id="email" value="[[!+fi.email]]"> <label for="comment">Comment</label> <textarea name="comment" id="comment" cols="30" rows="10" value="[[!+fi.comment]]"></textarea> <input type="submit" value="Submit"> </form>
(префикс fi при желании можно изменить свойством placeholderPrefix при вызове сниппета)
-
Создаем чанк письма, которое будет приходить на почту после отправки результатов формы. К примеру mailtpl.feedback:
/* В качестве плейсхолдеров указывается код поля, который был записан в форме после префикса fi*/ <p>Имя: [[+name]]</p> <p>Email: [[+email]]</p> <p>Комментарий: [[+comment]]</p>
-
Вызываем сниппет FormIt
[[!FormIt? &hooks=`email` &emailFrom=`donotreply@yourdomain.com` &emailTpl=`mailtpl.feedback` &emailTo=`donotreply@yourdomain.com, admin@yourdomain.com` &emailSubject=`Письмо с сайта yourdomain.com` &successMessage=`Сообщение отправлено` ]]
-
К коду выше добавляем параметры для проверки заполненности обязательных полей и другие параметры проверки:
&validate=`name:required, email:email:required, comment:required` /* К полю email добавлен параметр :email, он проверяет правильность написания адреса электронной почты */
-
Добавим оповещение пользователя, о неправильно заполненном поле. В специально отведенное для сообщения об ошибке место (к примеру в тег <label>) вставляем код:
[[!+fi.error.placeholder_code:notempty=`<span>Обязательное поле не заполнено</span>`]]
Вместо оповещения об ошибках рядом с полями, можно создать специальный блок, в котором будут указаны все ошибки разом. Для этого надо обернуть код выше в специальный плейсхолдер, примерно так:
[[!+fi.validation_error_message:!empty=` <div class="alert"> <h3>Пожалуйста, исправьте следующие ошибки:</h3> <ul> [[!+fi.error.name:!empty=`<li><a href="[[*uri]]#name">Поле «Имя» не заполнено</a></li>`]] [[!+fi.error.email:!empty=`<li><a href="[[*uri]]#email">Поле «Email» не заполнено</a></li>`]] [[!+fi.error.comment:!empty=`<li><a href="[[*uri]]#comment">Поле «Комментарий» не заполнено</a></li>`]] </ul> </div>`]]
Анти-спам
- Капча (captcha) — распространенный метод. Некоторые виды этой защиты боты научились распознавать и обходить. Самой эффективной на данный момент является reCAPTCHA от Google. Минусы — дополнительное поле, которое надо заполнить пользователю.
Для FormIt есть специальные хуки с капчами math и reCaptcha (смотрите в резделе Хуки); - Скрытые поля ввода
/* Скрытое поле. Не эффективный метод, т.к. боты научились не заполнять скрытые поля */ <input type="hidden" name="antispam" value=""> /* Обычное поле, скрытое за счет css */ <input type="text" id="antispam" value=""> /* Такие поля можно добавлять с использованием JS, это усилит защиту, т.к. большинство ботов не использует js */ /* При использовании скрытых полей в FormIT надо добавить проверку*/ [[!FormIt? &validate=`antispam:blank`]]
- Для FormIt есть специальный хук; проверяющий указанный email в спам-листе. Данный метод помогает далеко не всегда.
[[!FormIt? &hooks=`spam` &spamCheckIp=`true`]]
-
Метод от Ильи Уткина, добавить замаскированное поле, которое будет отвечать на спам успешной отправкой, благодаря чему спам-бот и его хозяин сочтут что сообщение отправлено:
/* Создаём сниппет checkSpam */
<?php
if ($_POST['surname']) { // проверяем наше поле на пустоту
echo $AjaxForm->success('Ваше сообщение отправлено');
die();
} else {
return true;
}
/* Добавляем в форму поле, по которому будем фильтровать */
<input type="text" name="surname" class="form-input" placeholder="Фамилия">
/* Маскируем поле */
input[name="surname"] {
display: block;
width: 2px;
height: 3px;
margin-bottom: -3px;
opacity: 0.01;
}
/* Добавляем сниппет checkSpam в качестве хука перед email */
`hooks` => `checkSpam,email...`
AjaxForm
Сниппет ajaxForm представляет из себя надстройку над FormIt реализующую Ajax вызов. Вызов сниппета
[[!AjaxForm?
&snippet=`FormIt`
&form=`tpl.AjaxForm.example`
&emailTpl=`mailtpl.feedback`
&hooks=`email`
&emailSubject=`Письмо с сайта yourdomain.com`
&emailFrom=`donotreply[@]yourdomain.com`
&emailTo=`donotreply@yourdomain.com, admin@yourdomain.com`
&validate=`name:required,
email:email:required,
comment:required,
antispam:blank`
&successMessage=`Сообщение отправлено`
]]
Подробнее на странице об AjaxForm
Параметры FormIt
По умолчанию | Описание | |
hooks | Скрипты, которые запускаются после того как нажимается кнопка отправки. Сюда также можно записать имя сниппета, который должен воспроизводиться после отправки формы. | |
preHooks | Скрипты, которые запускаются после загрузки формы. Сюда также можно записать имя сниппета, который должен воспроизводиться после отправки формы. | |
submitVar |
Если параметр установлен, не будет начинаться обработка формы, если эта переменная POST не передается. Может применяться при конфликте нескольких форм на странице.
|
|
validate | Разделенный запятыми, список полей, для проверки. Формат записи name:validator (например: username:required, email:email:required). Валидаторов у поля может быть несколько. | |
validationErrorMessage | A form validation error occurred. Please check the values you have entered. | Текст сообщения об ошибке. Может содержать , если надо отобразить список всех ошибок. |
validationErrorBulkTpl | [[+error]] | Шаблон сообщения об ошибке валидации |
errTpl | [[+error]] | Оболочка html для сообщений об ошибках. Примечание: не чанк, только HTML. |
customValidators | Разделенный запятыми, список имен пользовательских валидаторов (для параметра validate), которые будут использоваться в этой форме. Они должны быть явно указаны здесь, иначе не будут запущены. | |
clearFieldsOnSuccess | 1 | Если true, очистит поля после успешной отправки формы, которая не будет перенаправлена. |
store | 0 | Если true, сохранит данные в кэше для извлечения, с использованием компонента FormItRetriever. |
storeTime | 300 (5 минут) | Если для параметра store установлено значение true, этот параметр указывает количество секунд для хранения данных из представления формы. |
storeLocation | cache | При использовании хранилища это определяет, где форма сохраняется после отправки. Возможными параметрами являются «cache» и «session» |
placeholderPrefix |
fi. |
Префикс для плейсхолдеров полей формы, которые должен обрабатывать FormIt. Разделитель в виде точки '.' обязателен. |
successMessage | Если не используется переадресация, отобразите это сообщение об успешном завершении после успешной отправки. | |
successMessagePlaceholder | fi.successMessage | Имя плейсхолдера, для размещения сообщения об успешной отправке. |
redirectTo | ID страницы, с сообщением отображающимся после отправки формы. Является частью хука redirect, работает только с его подключением. | |
allowFiles | true | Разрешены ли файлы для публикации. Отправленные файлы хранятся во временном каталоге, для предотвращения потери файлов в многоэтапных формах. |
Хуки (hooks)
Хуки — специальные скрипты, которые запускаются во время обработки FormIt. Хуки могут быть связаны, к примеру, второй хук начнет выполняться только если первый отработан успешно.
Список предустановленных хуков
Email — отправляет результат формы на почту (активирует функцию mail()).
Доступные настройки:
- emailTpl — обязательный параметр. Шаблон письма который должен приходить на почту.
- emailSubject — тема письма
- emailUseFieldForSubject — если установлен параметр 1, и поле emailSubject не установлено, то в качестве темы письма будет использоваться поле.
- emailTo — разделенный запятыми список почтовых адресов, на который отправлять письма.
- emailToName — необязательный параметр. Разделенный запятыми список пар Имя/Адрес, на который отправлять письма.
- emailFrom — необязательный параметр. Адрес электронной почты который будет указан в качестве отправителя. Если не установлен, будет указан первый найденный адрес по следующему списку: поле email из формы, параметр emailsender из настроек системы. Стоит учесть, что в качестве отправителя следует указывать существующий адрес электронной почты, во избежании проблем с попаданием писем в спам, из-за нарушений правил SPF / DMARC.
- emailFromName — необязательный параметр. Имя которое должно быть указано в поле From.
- emailHtml — необязательный параметр. Разрешена ли отправка письма в html формате. По умолчанию — 1, разрешена.
- emailConvertNewlines — необязательный параметр. Если установлено 1, все символы новой строки преобразуются в теги br.
- emailReplyTo — электронная почта для отправки ответа. Если не задано, отправляется на адрес указанные в поле email, если таковой отсутствует, используется параметр emailFrom.
- emailReplyToName — необязательный параметр. Имя для параметра emailReplyTo.
- emailCC — разделенный запятыми список адресов для отправки копий сообщения (CC).
- emailCCName — необязательный параметр. Разделенный запятыми список пар Имя/Адрес, для отправки копий сообщения (СС)
- emailBCC — разделенный запятыми список адресов для отправки скрытых копий сообщения (BCC).
- emailBCCName — необязательный параметр. Разделенный запятыми список пар Имя/Адрес, для отправки скрытых копий сообщения (BСС)
- emailMultiWrapper — обертка для отправленных значений параметров типа чекбокс / мультивыбор. По умолчанию отправляются только значения.
- emailMultiSeparator — разделитель для отправленных значений параметров типа чекбокс / мультивыбор. По умолчанию новая строка.
FormItAutoResponder — отправляет автоответ автору сообщения.
- fiarTpl — обязательный. Шаблон для сообщения автоответчика;
- fiarSubject — тема письма;
- fiarToField — имя поля формы для использования в качестве электронной почты подателя. По умолчанию «электронная почта».
- fiarFrom — необязательный. Если установлено, укажите адрес From: для электронной почты. По умолчанию используется настройка системы электронной почты.
- fiarFromName — необязательный. Значение From: для электронной почты.
- fiarSender — необязательный. Заголовок отправителя электронной почты. По умолчанию используется настройка системы электронной почты.
- fiarHtml — необязательный. Должно ли электронное письмо должно быть в формате HTML. Значение по умолчанию равно true.
- fiarReplyTo — обязательный. Адрес электронной почты для ответа.
- fiarReplyToName — необязательный. Имя поля Reply-to.
- fiarCC — список электронных писем для отправки через cc.
- fiarCCName — необязательный. Список имен, разделенных запятыми, для сопряжения с значениями fiarCC.
- fiarBCC — список писем с разделителями-запятыми для отправки через ОЦК.
- fiarBCCName — необязательный. Список имен, разделенных запятыми, для сопряжения с значениями fiarBCC.
- fiarMultiWrapper — обнуляет значения, представленные флажками / мультивыбираемыми с этим значением. По умолчанию используется только значение.
- fiarMultiSeparator — отделяет флажки / мультивыборы с этим значением. По умолчанию используется новая строка. ( "\ П")
- fiarFiles — необязательный. Список файлов, разделенных запятыми, для добавления в качестве вложения в электронное письмо. Вы не можете использовать URL-адрес здесь, а только локальный путь к файловой системе.
- fiarRequired — необязательный. Если установлено значение false, крюк FormItAutoResponder не останавливается, когда поле, определенное в 'fiarToField', остается пустым. Значение по умолчанию равно true.
math — добавляет математическую капчу к форме.
Подобная капча выглядит как вопрос формата: 12 + 23?
Для ее интеграции надо добавить math к параметру &hooks и валидацию к соответствующему полю
&hooks=`math,email`
&validate=`math:required`
В нужное место формы вставить вызов
<label>[[!+fi.op1]] [[!+fi.operator]] [[!+fi.op2]]?</label>
[[!+fi.error.math]]
<input type="text" name="math" value="[[!+fi.math]]" />
<input type="hidden" name="operator" value="[[!+fi.operator]]" />
Дополнительные параметры хука math
По умолчанию | ||
mathMinRange | Минимальное допустимое число | 10 |
mathMaxRange | Максимальное допустимое число | 100 |
mathField | Имя поля с ответом | math |
mathOp1Field | Устаревший параметр. Имя поля для первого числа в уравнении. | op1 |
mathOp2Field | Устаревший параметр. Имя поля для второго числа в уравнении. | op2 |
mathOperatorField | Имя поля определяющего оператор уравнения | operator |
Кастомизация хука math
<label>[[!+fi.op1]] [[!+fi.operator:is=`-`:then=`minus`:else=`plus`]] [[!+fi.op2]]?</label>
Подобная запись выведет уравнение формата "23 plus 41?" или "50 minus 12?" вместо операторов -/+. Подобная запись немного усложнит задачу ботам.
recaptcha — добавляет рекапчу к форме.
Хук recaptcha предназначен для вставки в форму устаревшей версии рекапчи от гугл. На момент написания статьи лучше установить и использовать хук recaptchav2.
Для использования recaptcha надо добавить подключение в параметр hooks
&hooks=`recaptcha,email`
и вставить следующие теги в нужное место формы
[[+formit.recaptcha_html]]
[[!+fi.error.recaptcha]]
затем прописать ключи google в системные настройки:
- formit.recaptcha_private_key — секретный ключ;
- formit.recaptcha_public_key — ключ сайта;
- formit.recaptcha_use_ssl — использовать ssl для запросов рекапчи. По умолчанию false.
Дополнительные настройки хука recapture
- recaptchaJs — обьект JSON для вставки в параметры рекапчи, который будет генерировать соответствующий виджет. По умолчанию {}.
- recaptchaTheme — шаблон рекапчи который должен использоваться. По умолчанию не указан.
Ключи можно получить на странице google recapture
redirect — перенаправляет пользователя на специальный ресурс, при завершении отправки.
- RedirectTo — обязательный параметр. Идентификатор ресурса на который надо перенаправить пользователя после успешной отправки формы.
- redirectParams — объект параметров JSON для передачи URL-адреса переадресации.
Пример:
[[!FormIt?
&hooks=`redirect`
&redirectTo=`212`
&redirectParams=`{"user":"123","success":"1"}`
]]
<!--
С redirectParam формат полученного адреса будет таким
test.html?user=123&success=1
-->
При переадресации, значения полей формы не будут доступны на конечном ресурсе. Если необходимо передать значения полей формы, можно использовать свойство &store компонента FormItRetriever.
spam — проверяет все поля формы, указанные в свойстве spamEmailFields, на фильтр спама через StopForumSpam. Если пользователь помечен как спамер, форма покажет сообщение об ошибке.
- spamEmailFields — необязательный. Список полей электронной почты с разделителями-запятыми для проверки. По умолчанию «электронная почта».
- spamCheckIp — если true, будет также проверяться IP-адрес пользователя. По умолчанию false.
[[!FormIt? &hooks=`spam`]]
Не рекомендуется использовать IP для проверки спама, поскольку спамеры могут легко изменять IP-адреса, а проверка IP-адресов может выдать ложное срабатывание.
FormItSaveForm — хук для сохранения результатов формы внутри панели менеджера.
Список расположен в Приложения (Extras) => FormIt. Доступные настройки:
- formName: имя формы. По умолчанию «form-{resourceid}».
- formEncrypt: если установлено ’1′ (true) — отправленная форма будет зашифрована перед сохранением в базе.
- formFields: разделенный запятыми список полей, которые будут сохранены. По умолчанию сохраняются все поля, включая кнопку отправки.
- fieldNames: изменение имени полей внутри панели менеджера. Если поле называется email2 вы можете изменить имя на «второй email». Пример: &fieldnames=`fieldname==newfieldname, anotherone==anothernewname`.
Дополнительные хуки
Помимо предустановленных хуков можно писать свои или скачивать их с репозиториев. Для написания своего хука можно использовать сниппет, указав в параметре hooks его название.
Список полезных хуков которые можно скачать:
recaptchav2 — хук для интеграции с рекапчей от гугл второй и третьей версии.
Для интеграции надо добавить подключение в параметр hooks:
&hooks=`recaptchav2,email`
// для 3 версии
&hooks=`recaptchav3,email`
и вставить следующие теги в нужное место формы:
[[!recaptchav2_render]]
[[!+fi.error.recaptchav2_error]]
// для 3 версии
[[!recaptchav3_render]]
[[!+fi.error.recaptchav3_error]]
затем прописать ключи google в системные настройки:
- recaptchav2.secret_key — секретный ключ;
- recaptchav2.site_key — ключ сайта.
для рекапси 3 версии используйте соответствующие настройки:
- recaptchav3.secret_key — секретный ключ;
- recaptchav3.site_key — ключ сайта.
Ключи можно получить на странице google recapture
Селекты, чекбоксы, переключатели
(selects, checkboxes, radio buttons)
Для множественных полей формы, таких как селекты, чекбоксы и переключатели, стандартный способ подключения не сработает. Для таких случаев в FormIt предусмотрены сниппеты FormItIsSelected и FormItIsChecked.
Оформление select поля
<select name="color">
<option value="blue" [[!+fi.color:FormItIsSelected=`blue`]] >Синий</option>
<option value="red" [[!+fi.color:FormItIsSelected=`red`]] >Красный</option>
<option value="green" [[!+fi.color:FormItIsSelected=`green`]] >Зеленый</option>
<!-- Способ заполнения с использованием phx фильтров -->
<option value="yellow" [[!+fi.color:is=`yellow`:then=`selected`]]>Желтый</option>
</select>
Оформление checkbox и radio поля
<label>Color: [[!+fi.error.color]]</label>
<input type="checkbox" name="color[]" value="blue" [[!+fi.color:FormItIsChecked=`blue`]] > Синий
<input type="checkbox" name="color[]" value="red" [[!+fi.color:FormItIsChecked=`red`]] > Красный
<input type="checkbox" name="color[]" value="green" [[!+fi.color:FormItIsChecked=`green`]] > Зеленый
У html чекбоксов есть особенность — если значение отсутствует, параметр не передаётся, это так же влияет на проверку заполненности поля. Для того, чтобы отправить пустое значение, необходимо добавить скрытое input поле
[[!FormIt? &validate=`color:required`]]
...
<label>Color: [[!+fi.error.color]]</label>
<input type="hidden" name="color[]" value="" />
<input type="checkbox" name="color[]" value="blue" [[!+fi.color:FormItIsChecked=`blue`]] > Синий
<input type="checkbox" name="color[]" value="red" [[!+fi.color:FormItIsChecked=`red`]] > Красный
<input type="checkbox" name="color[]" value="green" [[!+fi.color:FormItIsChecked=`green`]] > Зеленый
Таким образом можно проверить, выбран ли хотябы 1 флажок.
Если надо установить поле с массивом значений (группу флажков, с одинаковым именем, или множественный селект) в преХук, надо сперва раскодировать данные из json формата
$hook->setValue('цвет',json_encode(array('синий','красный','зеленый')));
Настройка целей для счетчиков
Самый простой способ отслеживать успешную отправку формы, без изменения кода компонента - добавить перехватчик в сообщение об успешной отправке:
&successMessage=`Ваше письмо успешно отправлено <script>yaCounterXXXXXXXX.reachGoal('form');</script>`
Возможные ошибки
— Если FormIt говорит об успешной отправке формы, но письмо на почту не приходит, стоит проверить
- правильную настройку mx записи на сервере;
- в вызове formIt указан ли адрес исходящей почты: &emailFrom=`mail@site.ru`
— Если FormIt или AjaxForm выдают 500 ошибку при отправке, причин может быть несколько, и все они связаны с проблемами на сервере. К примеру, если на сервере используется php ниже 5.4 (не рекомендуется для новых версий modx), то проблему можно решить установкой в файле .htaccess следующего параметра:
php_flag register_globals off
Если же на сервере стоит версия php 5.4 и выше, то искать проблему стоит в логах Modx (core/cache/logs/error.log) и сервера. Если записей в логах нет, попробуйте переустановить компоненты FormIt и AjaxForm, и посмотрите, не вылезают ли ошибки во время установки. Если компонент ругается на ошибки, проставьте соответствующим папкам на сервере права доступа 700. И попробуйте переустановить снова (кнопка reinstall может не помочь, иногда эффективнее воспользоваться uninstall). Подробнее об ошибке 500.
— Если в списке отправленных форм, на странице FormIt в админ панели, вместо нормального списка отображается массив символов — вероятно вы раньше времени перешли на php 7.1, спуститесь на 7.0, либо ждите фикса компонента.
Здравствуйте!
Позвольте представиться, меня зовут Марина. Более 10 лет я занимаюсь обслуживанием сайтов и развитием интернет проектов. Если вы хотите избавиться от хлопот связанных с созданием и поддержкой сайта, тогда вы попали по адресу. При работе с сайтами я предоставляю качественные услуги, ориентируясь на ваши индивидуальные потребности. Для связи со мной воспользуйтесь формой обратной связи.