программирование на PHP
Bullet (black) Email иконка RSS иконка
  • Урок 20. Форма обратной связи

    Февраль 25th, 2009 Александр 88 Комментариев

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

    • ограниченное число полей;
    • жестко заданный дизайн;
    • “Самодельная” капча, которая пропускала спам-ботов;
    • Система оповещения об ошибках работала не корректно.

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

    Детали

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

    1. Создание неограниченного числа полей ввода, select элементов, radio, checkbox и тд;
    2. Старая капча заменена на более продвинутую библиотеку от проекта kcaptcha, и содержит кнопку обновления изображения при невозможности разобрать символы на изображении;
    3. Возможность легко и просто указать обязательность/необязательность конкретного поля;
    4. Использование оповещений для конкретного поля;
    5. Валидация e-mail по шабону;
    6. Перенаправление на страницу с сообщением об успешной отправке;
    7. Возможность отправки анкеты/письма нескольким адресатам;
    8. Использование скрипта в качестве сбора данных, например анкета.
    9. Для отправки письма используется шаблон, дизайн и структуру которого можно изменить самостоятельно;
    10. Единый файл конфигурации;

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

    А теперь я думаю необходимо кратко объяснить по какому принципу будет работать наш скрипт. Начнем с шаблона самой формы.

    Шаблон анкеты/формы.

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

    index.php
    [cc lang="html"]



    Форма обратной связи

    Ваше имя:


    Чего Вам не хватает?



    Обедали ли Вы у нас ранее?

    Да

    Нет

    Не помню



    Какие сети ресторанов Вам знакомы?

    Макдональдс

    Ростикс

    Ромашка

    “А у нас во дворе”


    Введите код подтверждения:

    Refresh



    [/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"]







    [/cc]

    Далее все без изменений.

    Как видите после открытия тега <body> мы добавили вывод переменной $page. В этом месте будут выводиться уведомления об ошибках. Также в заголовке (<head></head>) страницы добавлена переменная $head. Она будет актуальна лишь в том случае, если вы установите режим редиректа на 1, т.е. при помощи javascript’а .

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

    Скачать скрипт формы обратной связи можно здесь.

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

    Google Bookmarks БобрДобр.ru Memori.ru rucity.com МоёМесто.ru Mister Wong
    rss-лентаПодпишись на RSS, впереди много интересного.

    88 Responses to “Урок 20. Форма обратной связи”

    Страницы: [9] 8 7 6 5 4 3 2 1 » Show All

    1. 88
      vasiukiNo Gravatar Says:

      В чем может быть проблема: на локальном сервере форма работает, а на хостинге постоянно выкакивает ошибка – неверно веден код безопасности (капча)?

    2. 87
      AndreyNo Gravatar Says:

      Mik, молодец! Ты прав! Была ошибка в IE! дописал $_success_url = ’success.html’; – все отлично – работает на ура

    3. 86
      смвNo Gravatar Says:

      hgjhgh

    4. 85
      ИнтернетNo Gravatar Says:

      интересный скрипт) только вместо голого JS можно юзать jQuery) это намного удобнее)

    5. 84
      igorpankNo Gravatar Says:

      Очень прошу Вашей помощи! После отправки форми я получаю на указаный email письмо где вместо даних указаних в анкете я вижу крякозябри! Помогите пожалуйста исправить эту ошибку!
      Зарание спасибо

    6. 83
      АлександрNo Gravatar Says:

      Как сделать так, чтобы в теме получаемого письма был текст одного из полей (Тема), а письмо приходило с адреса, который был введён в форму?
      т.е. что присвоить “$_subject” и “$_headers .= ‘From:”?

    7. 82
      janeNo Gravatar Says:

      Я анкету на свой сайт добавила по такому шаблону, но почему то у меня в письме заполняются тока 4 первых поля и емейл, а дальше нет. Поля проставлены по порядку как в шаблоне письма так и на странице. В чем еще может быть дело, не подскадите?

    8. 81
      JaneNo Gravatar Says:

      Создала у себя анкету на сайте на основе шаблона, но почему то в письме приходят только первые 4 поля и емейл. А остальные не цепляются.. Все поля по порядку… Не подскажете в чем может быть дело?

    Страницы: [9] 8 7 6 5 4 3 2 1 » Show All

    Leave a Reply


freshcoder.ru © 2008 • При использовании материалов активная ссылка на сайт обязательна.
SEO Powered by Platinum SEO from Techblissonline