Как сделать форму обратной связи в ModX Revolution с помощью FormIt

Итак сегодня мы начинаем наш 9 урок MODX Revolution для новичков. Сегодня мы рассмотрим как создать простую контакт форму на нашем вебсайте используя сниппет FormIt. В предыдущем уроке мы ознакомились с работой Wayfinder. Научились делать вывод динамического меню с этим сниппетом. Сегодня опираясь на некоторые ваши знания о сниппетах попытаемся разобраться со сниппетом FormIt, урок будет довольно-таки длинным, поэтому сразу настраиваемся на интересную и плодотворную работу.

Что такое FormIt?

FormIt – это сниппет, который позволяет строить динамические формы всередине MODX Revolution. Если вы используете MODX Evolution, то вы возможно уже использовали eForm для генерирования и обработки своих форм. FormIt – это MODX Revolution эквивалент сниппета eForm, но это абсолютно иной сниппет.

Почему использовать именно FormIt?

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

Загрузка и установка FormIt

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

Подготовка шаблона

Я надеюсь, что сейчас вы уже прошли предыдущие уроки и портировали шаблоны внутренних страниц в вашем MODX сайте. Если вы используете тот же шаблон что и я, то вы увидите, что страница контактов является php страницой с PHP скриптами. Если вы использовали этот шаблон для построения статического сайта, то это будет как раз кстати, так как вы будете использовать для построения вашей формы существующий PHP код. В то же время, так как мы портируем наш шаблон в MODX, то нам не нужен этот код PHP, так как сам MODX разберется с построением всех наших форм. Всё, что нам нужно, – это HTML код формы и затем мы используем FormIt, который сделает всю остальную работу.

Посмотрите на статическую страницу контактов, которая идет вместе с нашим шаблоном:

Форма контакта

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

Первое, что необходимо сделать – это убрать HTML/CSS код и портировать его в MODX, если вы это уже не сделали. Так как моя контакт страница – это на самом деле PHP скрипт, то я просто открыл эту страницу в браузере и посмотрел исходный код. Это позволило мне увидеть простой выводимый HTML без кода PHP. Далее я скопировал данный код и вставил его в MODX для формирования шаблона моей страницы контактов. Дальше я по обычной схеме использовал несколько чанков для упрощения работы, то как мы уже делали на предыдущих уроках. И вот что у меня получилось:

Код
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en-US">
<head profile="http://gmpg.org/xfn/11">
[[$7in1-header]]
</head>
<body>
[[$7in1-logo-nav-search-bar]]
<div id="page_container">
<div id="container_bkgnd_btm">
<div id="page_content">
<div id="post-29">
<h2>[[*pagetitle]]</h2>
<div>
<p>Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enijusto, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pedemollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.Aenean vulputate eleifend tellus.</p>                                    </div>
</div>
<br />
<div></div>
<div id="contactInfo">
<div>Address:</div>
<div>123 Street Name, Suite #</div>
<div></div>
 
<div></div>
<div>City, State 12345, Country</div>
<div></div>
<div>Phone:</div>
<div>(123) 123-4567</div>
<div></div>
<div>Fax:</div>
<div>(123) 123-4567</div>
<div></div>
<div>Toll Free:</div>
<div>(800) 123-4567</div>
<div></div>
</div>
<div></div>
<div id="contact-wrapper">
[[*content]]
</div><!-- end contact-wrapper -->
</div>
<!-- end page_content -->
<div id="sidebar">
[[$7in1-contact-sidebar]]
<!-- end sidebar -->
</div>
<!-- end container_bkgnd_btm -->
</div>
<!-- end page_container -->
<div></div>
<div id="bottom_lid"> </div>
[[$7in1-bottomwidgets]]
<div id="footer_lid"> </div>
[[$7in1-footer]]
</body>
</html>

Я сохранил этот шаблон под названием 7in1-contact и назначил его шаблоном страницы контактов.

Вы узнаете некоторые из чанков (шапка и подвал) из наших предыдущих уроков, а также появилось несколько новых чанков. Я укажу вам их для просмотра, они будут полезны тем, кто использует этот же шаблон, что и я.

Важной особенностью здесь является та, что я заменил текст Contact в h2 тегах чанком [[*pagetitle]], который всплывет в вашей памяти, если вы внимательно прошли мои уроки.

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

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

Приступим к нашей форме. Для начала я заменил HTML код для формы, который содержался между div тегами “contact-wrapper” и заменил его тегом [[*content]]. Это значит, что всё в основном поле контента появится в моей странице контактов на этом месте. Поэтому сейчас страница контактов будет иметь такой вид:

Форма контакта

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

Как использовать сниппет FormIt

Итак, чтобы FormIt заработал, вам необходимо разместить вызов сниппета и HTML код формы в месте контакт формы. Если вы используете eForm сниппет MODX Evolution, то вам необходимо создать tpl шаблон для вашей формы, а затем вызвать его в сниппете, но при использовании FormIt вам не нужно вызывать форму в сниппете, вместо этого вы размещаете форму после вызова сниппета.

Давайте взглянем на вызов сниппета. Документация FormIt официального сайта MODX содержит отличный пример формы контакта и мы модифицируем его и используем в нашем случае. Будет полезно почитать документацию по этой ссылке http://rtfm.modx.com/display/ADDON/FormIt

Первое, что вы видите, когда смотрите на документацию – это то, что вам необходимо определить хуки вашего FormIt вызова. Хуки – это скрипты, которые срабатывают при вызове вашего сниппета. Вы можете связывать их вместе, но важно знать, что они исполняются последовательно и если один выдаст ошибку, то не сработают и остальные. Существуют предхуки и обычные хуки, но сейчас нас будут интересовать только нормальные хуки, которые запускаются после подтвержения и обработки формы. Вы можете создать собственные пользовательские хуки, но пока будем использовать обычные хуки.

Первый необходимый хук, который посылает электронную почту – это email и он имеет несколько параметров задокументированных здесь (http://rtfm.modx.com/display/ADDON/FormIt.Hooks.email). Выберите нужные для создания формы контактов параметры. Давайте сформируем наш вызов сниппета:

Код
[[!FormIt?
&hooks=`email`
&emailTpl=`sentEmailTpl`
&emailSubject=`Message from Learn MODx Revo Website`
&emailTo=`me@myemailaddress.com`
]]

Как видно мы использовали вызов сниппета с одним хуком – email, и определили для него три параметра &emailTpl, &emailSubjectи &emailTo. Убедитесь что параметру &emailTo вы присвоили ваш email адрес вместо показаного в примере me@myemailaddress.com.

Параметр emailTpl определяет чанк, который содержит шаблон для сообщения высылаемого формой. Перед созданием этого чанка нам нужно добавить форму, которую будет заполнять пользователь. Как я уже сказал до этого, мы будем использовать код HTML для формы, который содержался в нашем шаблоне и модифицируем его для работы с вызовом нашего сниппета FormIt call. Сырой код выглядит вот так:

Код
<form id="contactForm" method="post" action="#contact-wrapper">
<strong>Please use the form below to send us an email:</strong>
<div>
<label for="contact_name">Name </label><em>(required, at least 2 characters)</em><br />
<input id="contact_name" name="contact_name" size="30" minlength="2" value="" />
</div>
<div>
<label for="contact_email">E-Mail </label><em>(required)</em><br />
<input id="contact_email" name="contact_email" size="30"  value="" />
</div>
<div>
<label for="contact_phone">Phone </label><em>(optional)</em><br />
<input id="contact_phone_NA_format" name="contact_phone_NA_format" size="14" value="" maxlength="14" />
<label for="contact_ext">ext. </label>
<input id="contact_ext_NA_format" name="contact_ext_NA_format" size="5" value="" maxlength="5" />
</div>
<div>
<label for="contact_message">Your comment </label><em>(required)</em><br />
<textarea id="contact_message" name="contact_message" cols="70" rows="7"></textarea>
</div>
<div>
<input name="submit" type="submit" value="Submit"/>
</div>
</form>

Нам нужно немного изменить эту форму, чтобы FormIt мог ее обработать. Первое, что мы сделаем – это поменяем поменяем действие, чтобы оно указывало на текущую страницу, так как именно здесь находиться вызов сниппета FormIt. Мы делаем ссылку на текущую страницу используя синтаксис MODX Revo: [[~[[*id]]]]. Если вы посмотрите внимательно на этот вызов, то увидите то, что внутренний блок – это просто тег для ID поля: [[*id]] и внешняя часть – это тег для привязки url, например: [[~123]]

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

Результат выглядит приблизительно так:

Код
<form id="contactForm" method="post" action="[[~[[*id]]]]">
<strong>Please use the form below to send us an email:</strong>
<div>
<label for="contact_name">Name </label><em>(required, at least 2 characters)</em><br />
<input id="contact_name" name="contact_name" size="30" minlength="2" value="[[!+fi.contact_name]]" />
</div>
<div>
<label for="contact_email">E-Mail </label><em>(required)</em><br />
<input id="contact_email" name="contact_email" size="30"  value="[[!+fi.contact_email]]" />
</div>
<div>
<label for="contact_phone">Phone </label><em>(optional)</em><br />
<input id="contact_phone_NA_format" name="contact_phone_NA_format" size="14" value="[[!+fi.contact_phone_NA_format]]" maxlength="14" />
<label for="contact_ext">ext. </label>
<input id="contact_ext_NA_format" name="contact_ext_NA_format" size="5" value="[[!+fi.contact_ext_NA_format]]" maxlength="5" />
</div>
<div>
<label for="contact_message">Your comment </label><em>(required)</em><br />
<textarea id="contact_message" name="contact_message" cols="70" rows="7">[[!+fi.contact_message]]</textarea>
</div>
<div>
<input name="submit" type="submit" value="Submit"/>
</div>
</form>

Быстрый способ это сделать можно сравнив вашу контактную форму с формой представленной в документации FormIt. Также вы можете начать с формы в документации и в ней просто поменять классы для соответсвия вашей форме.

Далее разместите вызов сделанного нами сниппета в области контента вашей страницы Contact, а далее вставьте ваш код формы после вызова сниппета. Область контента должна содержать:

Код
[[!FormIt?
&hooks=`email`
&emailTpl=`sentEmailTpl`
&emailSubject=`Message from Learn MODx Revo Website`
&emailTo=`me@myemailaddress.com`
]]
<form id="contactForm" method="post" action="[[~[[*id]]]]">
<strong>Please use the form below to send us an email:</strong>
<div>
<label for="contact_name">Name </label><em>(required, at least 2 characters)</em><br />
<input id="contact_name" name="contact_name" size="30" minlength="2" value="[[!+fi.contact_name]]" />
</div>
<div>
<label for="contact_email">E-Mail </label><em>(required)</em><br />
<input id="contact_email" name="contact_email" size="30"  value="[[!+fi.contact_email]]" />
</div>
<div>
<label for="contact_phone">Phone </label><em>(optional)</em><br />
<input id="contact_phone_NA_format" name="contact_phone_NA_format" size="14" value="[[!+fi.contact_phone_NA_format]]" maxlength="14" />
<label for="contact_ext">ext. </label>
<input id="contact_ext_NA_format" name="contact_ext_NA_format" size="5" value="[[!+fi.contact_ext_NA_format]]" maxlength="5" />
</div>
<div>
<label for="contact_message">Your comment </label><em>(required)</em><br />
<textarea id="contact_message" name="contact_message" cols="70" rows="7">[[!+fi.contact_message]]</textarea>
</div>
<div>
<input name="submit" type="submit" value="Submit"/>
</div>
</form>

После сохранения превью формы выглядит вот так:

Форма контакта

Отлично, форма выглядит в точности как оригинал. Но нам нужно протестировать её и посмотреть как MODX делает всю работу. Перед тестированием давайте создадим сообщениее, которое будет отправлено получателю с вебсайта. Этот чанк emailTpl мы обозначили в нашем FormIt вызове.

Мы используем заполнители для отправки необходимой информации из формы и мы ссылаемся на них, используя имена соответствующих полей. В моем случае я хочу знать все детали и контактную инфомацию введённую в форму. Поэтому я создал чанк sentEmailTpl и добавил к нему следующее:

Код
[[+contact_name]] left you the message below on the Learn MODx Revolution website: <br />
<strong>[[+contact_message]]</strong><br />
You can respond to [[+contact_name]] by email at <a href="mailto:[[+contact_email]]">[[+contact_email]]</a> or by phone at [[+contact_phone_NA_format]] (ext[[+contact_ext_NA_format]]

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

Теперь давайте протестируем нашу контактную форму. .

Тестирование FormIt формы

Проверим почту и увидим, что получено сообщение:

Отправленное через FormIt сообщение

Вы видите, что введенный текст в поле параметра тема сниппета FormIt оказалась строчкой нашей строчкой темы.

Давайте откроем сообщение и увидим были ли заменены корректно наши заполнители действительным содержимым формы:

Содержание FormIt сообщения

Единственной вещью, которую я заметил – это то, что я забыл добавить закрывающую скобку после (ext в моем шаблоне. Остальное выгдядит отлично и форма работает.

Добавлениепроверки

Следующей вещью, которую вы заметите – это то, что форма имеет поля, которые нужно обозначить как «обязательные для заполения», такие как: имя, имейл и комментарий. Дополнительно имена должны быть длинной более чем две буквы. Мы добавляем проверку к нашей форме, используя свойство &validate (смотрите ссылку в конце записи). Существует несколько встроенных валидаторов и мы будем использовать их в нашем вызове. Отмечу, что валидаторы могут быть связанными, поэтому если вам нужно проверить несколько вещей в одном поле, например, имя обязательно к заполнению И оно должно быть больше двух букв, то вы связываете эти два валидатора вместе. Поэтому для поля имя, первым шагом будет проверка наличия имени:

Код
&validate=`contact_name:required`

Теперь добавим второй валидатор:

Код
&validate=`contact_name:required:minLength=`2` `

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

Маленькая поправочка Шон МакКормик (разработчик FormIt сниппета и один из разработчиков ядра MODX) только что научил меня кое-чему новому в разделе комментариев. Вместо использования двух обратных кавычек, вы можете использовать тильды ^ :

…то бишь с соединёнными валидаторами, которые передают параметры, вы можете сделать так:

Код
&validate=`contact_name:required:minLength=^2^`

Отлично, давайте продолжим и добавим проверку в наш вызов FormIt.

Код
[[!FormIt?
&hooks=`email`
&emailTpl=`sentEmailTpl`
&emailSubject=`Message from Learn MODx Revo Website`
&emailTo=`me@myemailaddress.com`
&validate=`contact_name:required:minLength=`2`,
contact_email:email:required,
contact_message:required`
]]

Теперь же, если какой-нибудь Вася Петров пытается послать сообщение и вместо своих имени и фамилии ставит инициалы, то форма выдаст ошибку:

Проверка формы

Для вывода ошибок вам необходимо воспользоваться чанком вывода ошибки работы спиппета FormIt:

[[!+fi.error.attibute_name]], где attribute_name – имя атрибута вашей контакт формы.

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

Код
<label for="attribute_name">
        Attribute:
        <span class="error">[[!+fi.error.attribute_name]]</span>
</label>

Возле каждого атрибута, который мы проверяем – подвергаем валидации.

Если вас интересует откуда появились данные сообщения, то они закрепленны в Lexicon за formit. Зайдите в System->LexiconManagement, и далее поменяйте в выпадающем списке “core” на “formit” и далее вы увидите эти сообщения. Там вы можете поменять их либо же добавить свои собственные.

Добавление своих сообщений в Лексикон

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

Борьба со спамом

Теперь мы знаем как работает наша форма и мы получаем сообщения и проверка поля работает. Осталось выяснить как же бороться с попытками ботов высылать спам через нашу форму. Сниппет FormIt имеет два встроенных способа решения данной проблемы. Одна – это spam хук и вторая – это reCaptcha хук.

Спам хук просто проверяет поля, которые вы настроили согластно спам фильтра через http://www.stopforumspam.com/. Если они совпадают, то тогда высвечиваетсчя ошибка напротив поля(ей) и сообщение просто не посылается. Больше вы сможете почитать об этом здесь: http://rtfm.modx.com/display/ADDON/FormIt.Hooks.spam. Мы будем использовать значения по умолчанию для спам хука, который будет проверять поле имейл адреса.

Таким образом в нашем параметре хуков в FormIt добавим спам хук:

Код
&hooks=`spam,email`

Хук reCaptcha работает на базе the reCaptcha service для обеспечения поддержки вашей формы. Для использования reCaptcha вам вначале необходимо иметь бесплатный аккаунт на http://www.google.com/recaptcha. После создания аккаунта добавте домен вашего сайта и вам выдадут два ключа: частный ключ и публичный ключ. Вы можете использовать эти ключи на ваших доменнах либо субдоменнах. Если вы создаете глобальный ключ, то вы можете использовать его на множестве доменов.

Получение ключа каптчи

Теперь необходимо ввести эти два ключа в системных настройках для сниппета formit. Зайдите в System->System Settings, и в выпадающем списке вместо core выберите formit.

Ввод ключей Captcha для FormIt

Перед вами появятся три поля, одно для частного ключа, одно для публичного и одно задаст запрос о том, хотите ли вы использовать SSL. Введите ключи от reCaptcha в эти два поля:

Ввод ключей Captcha для FormIt

Отлично, теперь можно добавить рекапча хук к нашему вызову FormIt:

Код
&hooks=`recaptcha,spam,email`
Порядок в котором размещены эти хуки очень важен. Как я уже говорил ранее, хуки выполняются последовательно и если один выдаёт ошибку, то остальные не выполняются. Поэтому крайне важно, чтобы спам хуки шли перед имейл хуками.

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

Код
[[+formit.recaptcha_html]]
[[!+fi.error.recaptcha]]

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

Форма FormIt c Captcha хуком

Перенаправление на страницу успешного выполнения

Сейчас форма сделана так, что как только сообщение успешно послано, то пользователь переходит на пустую форму контакта. Мы можем это поменять так, что пользователь отсылается на страницу, которая показывает, что сообщение успешно отослано. Чтобы это сделать мы используем хук редиректа. Нам нужно определить на какую страницу должен быть перенаправлен пользователь и делаем это используя параметр redirectTo и добавляем что-то типа &redirectTo=`123`, где 123 это идентификатор ID страницы куда будет перенаправлятся пользователь. Я просто добавлю хук в конце списка хуков и добавлю параметр redirectTo:

Код
[[!FormIt?
&hooks=`recaptcha,spam,email,redirect`
&emailTpl=`sentEmailTpl`
&emailSubject=`Message from Learn MODx Revo Website`
&emailTo=`mymail@gmail.com`
&validate=`contact_name:required:minLength=^2^,
contact_email:email:required,
contact_message:required`
&redirectTo=`10`
]]

После успешного выполнения формы, посетитель сайта будет отослан на страницу с ID of 10, которая является thank you странице (я создал ее и скрыл от меню).

Успешная отправка сообщения с помощью FormIt

Создание автоответчика

Последний хук о котором мы поговорим в даной записи – это хук автоответчика FormItAutoResponder hook, аон просто отсылает автоответ отсылателю комментария. Этот хук имеет несколько свойств (http://rtfm.modx.com/display/ADDON/FormIt.Hooks.FormItAutoResponder) но мы используем лишь некоторые из них в нашей форме. Вначале мы созданим шаблон содержащий имейл для обратной отсылки на имейл. Это единственное необходимое для заполнения поле. Я создал чанк с названием autoResponseTpl и добавил следующие строки:

Код
[[+contact_name]], Thank you for your message.  Someone will send you a reply in due course.<br />
<br />
For your reference, you left the following message at the Learn MODx Revolution website: <br />
<strong>[[+contact_message]]</strong>
<br />

Как вы видите я снова использовал заполнители так же, как и до этого в случае с sentEmailTpl. Теперь нужно добавть хук FormItAutoResponder и его свойства к вызову сниппета FormIt как показано ниже:

Код
[[!FormIt?
&hooks=`recaptcha,spam,email,redirect,FormItAutoResponder`
&emailTpl=`sentEmailTpl`
&emailSubject=`Message from Learn MODx Revo Website`
&emailTo=`yourmail@yourserver.com`
&validate=`contact_name:required:minLength=^2^,
contact_email:email:required,
contact_message:required`
&redirectTo=`10`
&fiarTpl=`autoResponseTpl`
&fiarSubject=`Thank You for Contacting Us`
&fiarToField=`contact_email`
&fiarFromName=`Learn MODx Website`
]]

Как вы видите выше я добавил не только необходимые свойства, но и несколько доступных для заполнения. Важно отметить реквизит &fiarToField который я определил как contact_email. Это важно, потому что если вы не установите его по умолчанию в “email” но ваше поле почты может иметь другое имя, как в моём случае.

Я протестирую эту форму отсылая сообщение, используя один из моих имейл адресов. Когда я проверю этот адрес, я увижу, что получил автоответ от формы с темой, как я определил в реквизите &fiarSubject и отослал от имени указаном в реквизите&fiarFromName:

FormIt сообщение

Как вы видите по полученному письму – оно соответстует тому, что мы задали в нашем чанке автоответчика

Заключение

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

Как домашнее задание – можете исследовать сниппет FormIt Retriever и узнайте, сможете ли вы интегрировать его в вашу контакт форму.

13830