-
Урок 20. Форма обратной связи
Февраль 25th, 2009 88 КомментариевДанный урок является продолжением 11 урока. В старом варианте мы рассматривали механизм работы скрипта по отправке почты с ограниченным (фиксированным) числом полей. С тех пор на мою почту свалилось много пожеланий , а так же призывов о помощи. Дело в том что многие использовали этот скрипт в своих проектах для организации формы обратной связи на сайте. Поэтому большинство новичков столкнулись с некоторыми проблемами:
- ограниченное число полей;
- жестко заданный дизайн;
- “Самодельная” капча, которая пропускала спам-ботов;
- Система оповещения об ошибках работала не корректно.
Для того чтобы избежать всех вышеперечисленных проблем я доработал скрипт, и внес в него массу улучшений, тем временем оставив его достаточно простым для использования и внедрения в дизайн.
Детали
Данный скрипт обратной связи обладает следующими характеристиками:
- Создание неограниченного числа полей ввода, select элементов, radio, checkbox и тд;
- Старая капча заменена на более продвинутую библиотеку от проекта kcaptcha, и содержит кнопку обновления изображения при невозможности разобрать символы на изображении;
- Возможность легко и просто указать обязательность/необязательность конкретного поля;
- Использование оповещений для конкретного поля;
- Валидация e-mail по шабону;
- Перенаправление на страницу с сообщением об успешной отправке;
- Возможность отправки анкеты/письма нескольким адресатам;
- Использование скрипта в качестве сбора данных, например анкета.
- Для отправки письма используется шаблон, дизайн и структуру которого можно изменить самостоятельно;
- Единый файл конфигурации;
Все выше перечисленные характеристики позволят вам настроить форму обратной связи за несколько минут.
А теперь я думаю необходимо кратко объяснить по какому принципу будет работать наш скрипт. Начнем с шаблона самой формы.
Шаблон анкеты/формы.
По умолчанию, в большинстве случаев шаблоны формы обратной связи содержит несколько полей, капчу и кнопку. Мы не будем отклонятся от стандартов и рассмотрим слегка расширенную форму, которая будет чем то похожа на анкету.
index.php
[cc lang="html"]
Форма обратной связи
[/cc]Каждый элемент формы, будь то однострочное текстовое или многострочное, радио кнопка или же чекбокс, все они имеют строго определенные имена. Т.е. name=”field[n]” , где n – номер поля. Если в нашей форме встречается тип chekbox, то каждому полю создаем дополнительный индекс массива, т.е. field[n][k] . Это необходимо для того, чтобы после отправки формы, получить несколько k-значений n-го элемента. Чтобы было понятно , посмотрите на код выше.
После того как были пронумерованы и заданы все поля ввода, необходимо добавить капчу и поле ввода для букв и цифр. В этом примере все файлы капчи лежат в отдельной папке kcaptcha. Для того чтобы вывести какой то код, нам необходимо обратиться к файлу img.php . В итоге в теге <img> в качестве источника указываем kcaptcha/img.php и id элемента – image. ID необходим для того чтобы при помощи яваскрипта обратиться к этому тегу.
Для того чтобы сделать функцию обновления “refresh” мы добавляем ссылку. Внутри тега <a> атрибуту onClick прописываем небольшую javascript-функцию, которая обращается к элементу с id = image ( document.getElementById(‘image’) ) и присваивает ему новый источник (src=’kcaptcha/img.php?rand=’+Math.round(1000 * Math.random())), а точнее передает скрипту img.php случайное число. В результате получаем возможность обновления капчи без перезагрузки страницы.В конце формы обязательно добавляем кнопку.
Вот и все, мы рассмотрели лишь небольшую часть нашего будущего скрипта. Далее необходимо перейти к файлу с настройками.
Файл настроек.
Файл конфигурации будет содержать несколько массивов. В любой момент можно будет произвести корректировку или добавить что то новое. Для того чтобы вы начали понимать о чем я говорю предлагаю обратиться к следующему фрагменту. Т.к. все поля у нас строго пронумерованы, то чтобы создать сообщение об ошибке для какого то конкретного поля, нам просто необходимо добавить элемент массива с тем же индексом что и поле.
Пример. Допустим у поля для ввода имени у атрибута name прописано значение field[1], тогда для того чтобы задать сообщение об ошибке мы создаем элемент в массиве $error с таким же индексом, т.е. $error['1'] = “Необходимо ввести имя<br/>”;
[cc lang="php"]
//Настраиваем массив ошибок
$error = array();
//Ошибки для каждого поля
$error['1'] = "Необходимо ввести имя
“;
$error['2'] = “Необходимо ввести номер телефона
“;
$error['3'] = ‘Пожалуйста, напишите несколько строк о нашем заведении
‘;
$error['4'] = ‘Пожалуйста, напишите несколько строк о наших недостатках
‘;
$error['5'] = ‘Вы не ответили на вопрос “Обедали ли Вы у нас ранее?”
‘;
$error['6'] = ‘Вы не ответили на вопрос “Какие сети ресторанов Вам знакомы?”
‘;[/cc]
Для поля field[email] задаем элемент массива $error['email'] и присваиваем ему любой текст:
[cc lang="php" first_line="12"]
//Служебные ошибки
$error['email'] = “Введите корректный e-mail адрес
“;
$error['captcha'] = “Не верно введен код подтверждения
“;
$error['render'] = “Извините, произошла непредвиденная ошибка
“;
$error['mailer'] = “Извините, произошла непредвиденная ошибка. Ваша анкета не была отправлена
“;
[/cc]Также в массиве $error существуют дополнительные элементы, такие как email, captcha, render, mailer.
1. $error['email'] – сообщение об ошибке в случае не корректного заполнения адреса эл.почты;
2. $error['captcha'] - сообщение об ошибке в случае не верного кода подтверждения;
3. $error['render'] – сообщение об ошибке в случае кривого формирования контента или его отсутствия;
4. $error['mailer'] сообщение об ошибке, если функция mail() возвращает ошибку;Далее необходимо настроить обязательность / необязательность отдельных полей. В файле конфигурации существует массив $requirements. Для того чтобы задать обязательность какого то поля, необходимо создать элемент массива с таким же индексом как и индекс этого поля и присвоить ему единицу, либо ноль.
Пример.
Допустим у поля для ввода имени у атрибута name прописано значение field[1], тогда для того чтобы задать условия обязательного заполнения этого поля необходимо создать в массиве $requirements элемент с таким же индексом и задать ему значение 1, т.е. $requirements['1'] = 1; Если нет необходимости для заполнения поля ставим значение 0.
Для поля e-mail – $requirements['email'] = 1;
[cc lang="php" first_line="17"]//Настраиваем обязательность(1)/необязательность(0)
$requirements = array();$requirements['email'] = 1;
$requirements['1'] = 1;
$requirements['2'] = 1;
$requirements['3'] = 1;
$requirements['4'] = 0;
$requirements['5'] = 0;
$requirements['6'] = 1;
[/cc]Далее настраиваем получателей письма.
Для этого существует массив $recipient. Для того чтобы внести получателя необходимо создать элемент массива и присвоить ему значение – эл.адрес получателя.
Пример.
[cc lang="php" first_line="27"]
$recipient[1] = ‘vasya@pupkin.ru’;
$recipient[2] = ‘freshcoder.ru@gmail.com’;
[/cc]
Письма будут уходить на адреса, которые вы укажите в этом массиве.Так как в теле письма будет использован html-код, то необходимо этот код написать, точнее оформить страницу и указать путь до этого шаблона. Например:
[cc lang="php" first_line="29"]
$_file = ‘tmpl/index.html’;
[/cc]
Как составлять шаблон мы рассмотрим чуть позже.Для того чтобы корректно сообщить пользователю о том что письмо было отправлено, мы перенаправляем его на соответствующую страницу. В конфигурационном файле переменной $_success_url необходимо присвоить путь. Пример:
[cc lang="php" first_line="30"]
$_success_url = ’success.html’;
[/cc]Теперь о методе редиректа. Т.к. на некоторых хостингах не поддерживается php функция header() , то мы дополним скрипт возможностью редиректа при помощи javascript’а и meta информации. В конфигурации лишь указываем какой из методов будет использован.
Для того чтобы задать режим переадресации надо поменять значение у переменной $_redirect , т.е. 0 – при помощи функции в php (header), 1 – при помощи js.
[cc lang="php" first_line="31"]
$_redirect = 0;
[/cc]
После указываем заголовки письма и тему.
[cc lang="php" first_line="32"]
//Заголовки письма
$_headers = ‘MIME-Version: 1.0′ . “\r\n”;
$_headers .= ‘Content-type: text/html; charset=windows-1251′ . “\r\n”;
$_headers .= ‘From: Сообщение‘. “\r\n”; //Тема с которой письмо будет приходить к вам на ящики
$_subject =’Вам пришла новая анкета’;
[/cc]Вот вроде и разобрали наш файл конфигурации. Далее рассмотрим шаблон письма.
Файл функций
Файл функций содержит всего 1 функцию – checkmail. Она проверяет адрес электронной почты по шаблону при помощи регулярного выражения
functions.inc.html
[cc lang="php"]
function checkmail($mail) {
// режем левые символы и крайние пробелы
$mail=trim($mail);
// если пусто - выход
if (strlen($mail)==0) return 0;
if (!preg_match("/^[a-z0-9_-]{1,20}+(\.){0,2}+([a-z0-9_-]){0,20}@(([a-z0-9-]+\.)+(com|net|org|mil|".
"edu|gov|arpa|info|biz|inc|name|[a-z]{2})|[0-9]{1,3}\.[0-9]{1,3}\.[0-".
"9]{1,3}\.[0-9]{1,3})$/is",$mail))
return 0;
return $mail;
}
?>
[/cc]Шаблон письма.
Т.к. мы используем единую систему нумерации полей, то просто необходимо в шаблоне подставить необходимые метки. Допустим у поля для ввода имени у атрибута name прописано значение field[1], тогда для того чтобы получить это значение в шаблоне мы ставим метку [FIELD1]. С остальными также. Для поле e-mail метка имеет вид [EMAIL] . Как выглядит шаблон в нашем случае смотрите ниже.
index.html
[cc lang="html"]
Поступило новое письмо.
Контактная информация
- имя: [FIELD1]
- телефон: [FIELD2]
- e-mail: [EMAIL]
Ответы
Общее впечатление:
[FIELD3]
То чего не хватает:
[FIELD4]
Ответ на вопрос: “Обедали ли Вы у нас ранее?” был дан ответ : [FIELD5]
Ответ на вопрос: “Какие сети ресторанов Вам знакомы?” был дан ответ : [FIELD6]
Служебная информация
- Дата: [DATA]
- IP-адрес: [IP]
- Браузер: [BROWSER]
- Со страницы: [URL]
[/cc]
В теле шаблона кроме данных из полей ( filed1 – field6), присутствует служебная информация:
1. Дата [DATA]
2. IP-адрес пользователя [IP]
3. Браузер пользователя [BROWSER]
4. Адрес страницы [URL]Сам шаблон будет храниться в папке tmpl. Если у вас будет другая папка, не забудьте исправить путь в файле конфигурации.
Ну вот и рассмотрели все то что придется делать ручками. Далее будет скрипт, который не требует вмешательств.
Обработка данных.
Давайте теперь разберем как устроен сам скрипт. Прежде всего необходимо произвести инициализацию сессии и подключить файл конфигурации и функций.
[cc lang="php"]
//Инициализация сессии
session_start();//Подключаем файл конфигурации
require("inc/config.inc.php");
//Подключаем файл с функциями
require("inc/functions.inc.php");
[/cc]После этого начинается логика:
[cc lang="php" first_line="9"]
//Были ли нажата кнопка
if(@$_POST['do']!=''){
//Создаем переменные
$_ERR='';
$page='';
$head='';
//Переопределяем переменную
$keystring = $_REQUEST['keystring'];
[/cc]При удовлетворении условия создаем пустые переменные, которые дальше нам будут необходимы. После переопределяем переменную, а точнее задаем переменной $keystring то значение, которое мы прочитали на изображении и ввели в соответствующее поле.
[cc lang="php" first_line="17"]
//Сравниваем
if ($keystring != $_SESSION['captcha_keystring'] OR empty($keystring)) {
//Составляем уведомление
$page.=’Ошибка: ’.$error['captcha'].’
‘;
unset($_SESSION['captcha_keystring']);
}
[/cc]Сравниваем значение переданное с формы со значением находящимся в сессии. Если оно отсутствует или введено не верно присваиваем переменной $page кусочек html кода и сообщение из массива ошибок $error.
Если все же код введен верно, то мы производим дальнейшую проверку.
[cc lang="php" first_line="24"]
//Если мэйл обязателен
if($requirements['email']==1){
//Проверяем
if(checkmail($_POST['field']['email']) === 0 ){ $_ERR.=$error['email'];}
} else { //Если нет
//Было ли заполнено
if($_POST['field']['email']!=”){
//Тогда проверяем
if(checkmail($_POST['field']['email']) === 0 ){ $_ERR.=$error['email'];}
}
}
[/cc]При проверке эл.адреса учитывается его обязательность, а также наличие. Например, если у нас в файле конфигурации эл.адрес указан как обязательный то будет работать первое условие. Внутри него мы проверяем корректность адреса , и если он не совпадает пишем в переменную $_ERR ошибку.
Если же адрес не обязателен, то в работу вступает исключение, которое все равно проверяет эл.адрес если он был введен.После этой проверки у нас может получиться 2 результата – либо переменная $_ERR пустая, либо нет и содержит сообщение об ошибке из массива $error.
Далее необходимо проверить переменные, которые были обязательны для заполнения. Здесь в работу вступает следующий блок:
[cc lang="php" first_line="35"]
//Запускаем цикл
for($i=1;$i<=count($requirements);$i++){
//Проверяем
if($requirements[$i] ==1) {
//Проверяем существование переменной
if(!isset($_POST['field'][$i]) OR $_POST['field'][$i]=='' ) { $_ERR.=$error[$i];}
}
}
[/cc]При помощи цикла for() мы организовываем перебор массива и проверку его ключа. Т.е. в нашем массиве $requirements содержится 6 переменных (см. файл конфигурации) поэтому цикл будет выполнен 6 раз. При каждом проходе будет осуществляться проверка значения в массиве под определенным индексом. Для примера рассмотрим поле filed[1] – имя человека.
//Проверяем
if($requirements[1] ==1) {
//Проверяем существование переменной
if(!isset($_POST['field'][1]) OR $_POST['field'][1]==” ) { $_ERR.=$error[1];}
}В массиве $requirements[1] = 1; т.е. данное поле обязательно для заполнения. Поэтому используем условие, которое проверяет все индексы по очереди, и если оно равно единице, то запускаем еще одно условие. Вложенное условие проверяет чтобы переменная не была пустой либо существовала. Если условие не выполняется, то в переменную $_ERR
записываем ошибку из массива $errror под индексом 1, т.е. $error['1'] = “Необходимо ввести имя<br/>”;
После такой циклической проверки мы получаем результат – либо переменная $_ERR пуста ( ошибок нет и все обязательные поля заполнены) , либо $_ERR содержит ошибки, причем они все склеиваются и в дальнейшем будут выведены одним блоком.После того как проверили поля мы можем начинать формировать тело сообщения, но прежде чем это делать мы создаем дополнительное условие, которое проверяет переменную $_ERR.
[cc lang="php" first_line="43"]
//Если есть ошибки
if($_ERR !=”) {
$page.=’Ошибка: ’.$_ERR.’
‘;
}
[/cc]
Т.е. если существуют ошибки, то в переменную $page прикрепляем сообщения об ошибках, если таковые есть. Если ошибок нет, то поступаем следующим образом:
[cc lang="php" first_line="47"]
else {
//Подгружаем шаблон формы
$_tmpl = @join(”,@file($_file));//Парсим шаблон
for($k=1;$k<=count($requirements);$k++){
//Проверяем массив ди это?
if(is_array($_POST['field'][$k])) {
//Формируем строку из массива
$_string = implode(",",$_POST['field'][$k]);
//Заменяем метку
$_tmpl = str_replace('[FIELD'.$k.']',$_string,$_tmpl);} else {
//Заменяем метки
$_tmpl = str_replace('[FIELD'.$k.']',$_POST['field'][$k],$_tmpl);}
}
//Заменяем метку эл.адреса
$_tmpl = str_replace('[EMAIL]',$_POST['field']['email'],$_tmpl);
//Заменяем служебные метки
$_tmpl = str_replace('[DATA]',date("d.m.Y H:i:s"),$_tmpl);
$_tmpl = str_replace('[IP]',getenv('REMOTE_ADDR'),$_tmpl);
$_tmpl = str_replace('[BROWSER]',getenv('HTTP_USER_AGENT'),$_tmpl);
$_tmpl = str_replace('[URL]',getenv('HTTP_REFERER'),$_tmpl);//Разбираем массив получателей
$_to = implode(",",$recipient);
[/cc]Начинается самое интересное. Сейчас объясню как происходит парсинг шаблона и замена меток на необходимые данные.
Чуть выше мы рассматривали файл шаблона письма, который содержит метки для соответствующих полей.Теперь необходимо этот шаблон прочитать в одну строку, для этого используем команду join() .
После того как мы получили строку, которая содержит метки типа [FILELD1], [FILELD2], [FILELDn] необходимо их заменить.
Для этого организуем цикл, который будет выполняться столько же раз, сколько содержится элементов в массиве $requirements, в нашем случае 6 раз.
При каждом проходе цикла необходимо при помощи функции str_replace произвести замену метки на данные. В качестве примера можно рассмотреть первый и шестой переход.Для первого перехода $k = 1, поэтому при замене будет участвовать поле [FIELD1]. На место этой метки запишется информация из переменной $_POST['field'][1] , т.е. имя. В случае с массивом (6 переход), если в поле с чекбоксом несколько галочек выбрано, то придется проверять $_POST['field'][N] на принадлежность к массиву. Если все же поле является массивом, то необходимо все элементы массива объединить в строку и произвести аналогичную замену. Только заменяющее здесь будет строка элементов.
После цикла заменяем статичные метки со служебной информацией и метку с адресом электронной почты.
//Заменяем метку эл.адреса
$_tmpl = str_replace(‘[EMAIL]‘,$_POST['field']['email'],$_tmpl);
//Заменяем служебные метки
$_tmpl = str_replace(‘[DATA]‘,date(“d.m.Y H:i:s”),$_tmpl);
$_tmpl = str_replace(‘[IP]‘,getenv(‘REMOTE_ADDR’),$_tmpl);
$_tmpl = str_replace(‘[BROWSER]‘,getenv(‘HTTP_USER_AGENT’),$_tmpl);
$_tmpl = str_replace(‘[URL]‘,getenv(‘HTTP_REFERER’),$_tmpl);После чего разбираем получателей в строку $_to = implode(“,”,$recipient); и отправляем письмо.
[cc lang="php" first_line="89"]
//Отправляем письмо
if(@mail($_to, $_subject, $_tmpl, $_headers)){
[/cc]При успешной отправки письма необходимо перенаправить пользователя на определенную страницу, которую мы указали в файле конфигурации под именем $_succes_url :
[cc lang="php" first_line="91"]
if($_redirect == 0){
//Перенаправляем пользователя на страницу
header(“Location:”.$_success_url);
}if($_redirect == 1) {
//Перенаправляем пользователя на страницу при помощи js с нулевой задержкой$head .= ‘
‘;
}
}
[/cc]Как и оговаривалось выше скрипт поддерживает два метода редиректа. В первом случае мы можем использовать функцию header() в php , во втором javascript . Для второго случая формируем новую переменную $head, в которую пишем соответствующий скрипт.
Если письмо не удалось отправить записываем в переменную $page соответствующее сообщение:
[cc lang="php" first_line="110"]
else {$page.=’
Ошибка: ’.$error['mailer'].’
‘;
}
[/cc]В заключении закрываем условия, удаляем сессию и проверяем переменную $page:
[cc lang="php" first_line="114"]
}}
if($page==”){ $page.=’
Ошибка: ’.$error['render'].’
‘;}
//Разрушаем сессию
unset($_SESSION['captcha_keystring']);
}
?>
[/cc]Дальше должен идти шаблон анкеты, тот самый фрагмент html кода, который мы рассматривали в самом начале, но с небольшими доработками:
[cc lang="html" first_line="126"]
=$head;?>
=$page;?>
[/cc]Далее все без изменений.
Как видите после открытия тега <body> мы добавили вывод переменной $page. В этом месте будут выводиться уведомления об ошибках. Также в заголовке (<head></head>) страницы добавлена переменная $head. Она будет актуальна лишь в том случае, если вы установите режим редиректа на 1, т.е. при помощи javascript’а .
Данный скрипт был написан под заказ, но так как заказчик не был против, я разместил его в уроках. Надеюсь многие почерпнут что то новое.
Скачать скрипт формы обратной связи можно здесь.
Пример я публиковать не стал, т.к. думаю всем понятен итог – придет письмо с информацией.
Подпишись на RSS, впереди много интересного.88 Responses to “Урок 20. Форма обратной связи”
Страницы: [9] 8 7 6 5 4 3 2 1 » Show All
Страницы: [9] 8 7 6 5 4 3 2 1 » Show All
Leave a Reply




Февраль 11th, 2010 at 01:28
В чем может быть проблема: на локальном сервере форма работает, а на хостинге постоянно выкакивает ошибка – неверно веден код безопасности (капча)?
Январь 24th, 2010 at 18:31
Mik, молодец! Ты прав! Была ошибка в IE! дописал $_success_url = ’success.html’; – все отлично – работает на ура
Январь 15th, 2010 at 07:05
hgjhgh
Декабрь 2nd, 2009 at 02:57
интересный скрипт) только вместо голого JS можно юзать jQuery) это намного удобнее)
Ноябрь 22nd, 2009 at 16:13
Очень прошу Вашей помощи! После отправки форми я получаю на указаный email письмо где вместо даних указаних в анкете я вижу крякозябри! Помогите пожалуйста исправить эту ошибку!
Зарание спасибо
Ноябрь 19th, 2009 at 18:55
Как сделать так, чтобы в теме получаемого письма был текст одного из полей (Тема), а письмо приходило с адреса, который был введён в форму?
т.е. что присвоить “$_subject” и “$_headers .= ‘From:”?
Ноябрь 19th, 2009 at 14:07
Я анкету на свой сайт добавила по такому шаблону, но почему то у меня в письме заполняются тока 4 первых поля и емейл, а дальше нет. Поля проставлены по порядку как в шаблоне письма так и на странице. В чем еще может быть дело, не подскадите?
Ноябрь 19th, 2009 at 11:48
Создала у себя анкету на сайте на основе шаблона, но почему то в письме приходят только первые 4 поля и емейл. А остальные не цепляются.. Все поля по порядку… Не подскажете в чем может быть дело?