Формы и РНР
Обработка данных в формах имеет много общего с обработкой переменных, передаваемых в URL, — эта тема подробно рассматривалась в
предыдущей главе.
Вводные примеры
Следующие практические примеры помогут вам быстрее освоить различные аспекты обработки форм в РНР. В этих примерах
продемонстрированы разные подходы к реализации интерактивных возможностей на сайте.
Пример 1: передача данных формы из одного сценария в другой
В первом примере представлена характерная ситуация — когда пользовательские данные вводятся на одной странице и отображаются на
другой. В листинге 10.2 приведен код формы для ввода имени пользователя и адреса электронной почты. Когда пользователь щелкает на
кнопке отправки данных (кнопка Go!), форма обращается к странице, приведенной в листинге 10.3. В свою очередь, листинг 10.3 выводит
переменные $name и $mail, переданные с запросом.
Листинг 10.2. Простая форма
Listing 10-2
Листинг 10.3. Отображение данных, введенных в листинге 10.1
Listing 10-3
// Вывести имя и адрес электронной почты.
print "Hi. $name!. Your email address is $email";
?>
В общих чертах происходит следующее: пользователь заполняет поля формы и нажимает кнопку отправки данных. Управление передается
странице, приведенной в листинге 10.3, где происходит форматирование и последующее отображение данных. Как видите, все просто.
Существует и другой способ обработки данных форм, при котором используется всего один сценарий. К недостаткам этого способа относятся
увеличение сценария и как следствие — затруднения с редактированием и сопровождением. Впрочем, есть и достоинства — уменьшение
количества файлов, с которыми вам приходится работать. Более того, в этом варианте сокращается избыточный код при проверке ошибок (эта
тема рассматривается ниже в данной главе). Конечно, в некоторых ситуациях работать с одним сценарием неудобно, но, по крайней мере, вы
должны знать об этой возможности. В примере 2 воспроизводится пример 1, но с использованием лишь одного сценария.
Пример 2: альтернативная обработка формы (с одним сценарием)
Обработка данных формы в одном сценарии реализуется относительно просто. Вы проверяете, были ли присвоены значения переменным
формы. Если значения присвоены, сценарий обрабатывает их (в нашем примере — просто выводит), а если нет — отображает форму. Решение
о том, было ли задано значение переменной или нет, принимается при помощи функции strcmp( ), описанной в главе 8. Пример реализации
формы с одним сценарием приведен в листинге 10.4. Обратите внимание: атрибут action формы ссылается на ту же страницу, в которой
определяется сама форма. Условная команда i f проверяет состояние переменной скрытого поля с именем $seenform. Если значение $seenform
не задано, форма отображается в браузере, а если задано — значит, форма была заполнена пользователем и введенные данные
обрабатываются сценарием (в данном примере — просто выводятся в браузере).
Листинг 10.4. Ввод данных на форме в одном сценарии
Listing 10-4
// Все кавычки внутри $form должны экранироваться,
// в противном случае произойдет ошибка.
$form = "
";
// Если форма ранее не отображалась, отобразить ее.
// Для проверки используется значение скрытой переменной $seenform.
if ($seenform != "у"):
print "$form";
else :
print "Hi. $name!. Your email address is $email";
endif;
?>
Учтите, что этот вариант создает определенные неудобства, поскольку при повторной загрузке страницы пользователь ничего не узнает о том,
правильно ли были заполнены поля формы. Процедура проверки ошибок рассматривается далее в этой главе, а пока достаточно запомнить,
что ввод данных можно осуществить при помощи одного сценария.
Теперь, когда вы представляете, как просто выполняются операции с формами, мы переходим к интересному примеру — автоматической
отправке данных пользователя по заданному адресу электронной почты. Эта возможность реализована в примере 3.
Пример 3: автоматическая отправка данных по электронной почте
Вывести пользовательские данные в браузере несложно, но вряд ли это можно назвать содержательной обработкой пользовательского ввода.
Один из способов обработки информации заключается в ее отправке по электронной почте — например, администратору сайта. Хотя при
помощи гиперссылки mailto: можно отправить сообщение прямо из браузера, следует учитывать, что внешние приложения электронной почты
настроены не на каждом компьютере. Следовательно, отправка сообщений с web-формы более надежно гарантирует, что сообщение будет
доставлено адресату.
В следующем разделе, mail( ), создается небольшая форма, в которой пользователь вводит информацию и комментарии по поводу сайта. Затем
данные форматируются соответствующим образом и передаются стандартной функции РНР mail( ). Но прежде чем переходить к построению
формы, необходимо предварительно рассмотреть синтаксис функции mail( ).
mail ( )
Функция mail( ) отправляет сообщение заданному адресату по электронной почте. Синтаксис функции mail( ):
boolean mail (string получатель, string тема, string сообщение [, string доп_заголовки])
В параметре тема, как нетрудно предположить, передается тема сообщения. Параметр сообщение содержит текст сообщения, а необязательный
параметр доп_за головки предназначен для включения дополнительной информации (например, атрибутов форматирования HTML),
пересылаемой с сообщением.
В системе UNIX функция mail( ) использует утилиту sendmail. В Windows эта функция работает лишь при наличии установленного
почтового сервера или если функция mail( ) связана с работающим сервером SMTP. Эта задача решается модификацией переменной
SMTP в файле php.ini.
Если вы сделали все необходимое и функция mail( ) работает в вашей системе, попробуйте выполнить следующий фрагмент (конечно, адрес
youraddress@yourserver.com заменяется вашим настоящим адресом электронной почты):
$email = "youraddress@yourserver.com";
$subject = "This is the subject";
$message = "This is the message";
$headers = "From: somebody@somesite.com";
mail ($email, $subject, $message, $headers);
Хотя при обширной переписке, конечно, следует использовать специализированные почтовые программы вроде majordomo
(http://www.greatcircle.com/majordomo), в простых случаях функции РНР mail( ) оказывается вполне достаточно.
Итак, после знакомства с функцией mail( ) можно применить ее на практике. В листинге 10.5 показано, как получить информацию от
пользователя и отправить ее по адресу, заданному администратором сценария.
Листинг 10.5. Пересылка пользовательских данных функцией mail( )
Listing 10-5
// Все кавычки внутри $form должны экранироваться.
// в противном случае произойдет ошибка.
$form = "
// Если форма ранее не отображалась, отобразить ее.
// Для проверки используется значение скрытой переменной $seenform.
if ($seenform != "у") :
print "$form"; else :
// Переменная $recipient определяет получателя данных формы
$recipient = "yourname@youremail.com";
// Тема сообщения
$subject = "User Comments ($name)";
// Дополнительные заголовки $headers = "From: $email";
// Отправить сообщение или выдать сообщение об ошибке
mail($recipient, $subject, $comments, $headers) or die("Could not send email!");
// Вывести сообщение для пользователя
print "Thank you $name for taking a moment to send us your comments!";
endif;
?>
Неплохо, правда? Листинг 10.5 работает так же, как листинг 10.4; сначала мы проверяем, отображалась ли форма ранее. Если это происходило,
программа вызывает функцию mail( ) и пользовательские данные отправляются по адресу, определяемому переменной $recipient. Затем в
браузере выводится благодарственное сообщение для пользователя.
Простейшим расширением этого примера будет отправка благодарственного сообщения по электронной почте (вторым вызовом mail( )).
Следующий пример развивает эту идею — пользователю предлагается на выбор несколько бюллетеней. Выбранные бюллетени отправляются
по электронной почте.
Пример 4: отправка запрашиваемой информации по электронной почте
В этом примере в форме создается несколько флажков, каждый из которых соответствует отдельному документу с информацией о сайте.
Пользователь устанавливает один, два или три флажка, вводит свой адрес, и запрашиваемые брошюры отправляются ему по электронной
почте. Обратите внимание на применение массива при работе с флажками — это упрощает проверку выбранных флажков, а также улучшает
структуру программы.
Информационные сообщения хранятся в отдельных файлах. В нашем примере используются три текстовых файла:
site.txt — информация о сайте;
team.txt — информация о талантливых разработчиках сайта;
events.txt — приглашение на очередное мероприятие.
Исходный текст примера приведен в листинге 10.6.
Листинг 10.6.Отправка информации, запрашиваемой пользователем
Listing10-5
$form = "
":
if ($seenform != "y") :
print "$form"; else :
$headers = "From: devteam@yoursite.com";
// Перебрать все пары "ключ/значение"
while ( list($key, Sval) = each ($information) ) :
// Сравнить текущее значение с "у" if ($val == "у") :
// Построить имя файла, соответствующее текущему ключу
$filename = "$key.txt":
$subject = "Requested $key information";
// Открыть файл
$fd = fopen ($filename, "r");
// Прочитать содержимое всего файла в переменную $contents = fread ($fd. filesize ($filename));
// Отправить сообщение
mail($email, $subject, $contents, $headers) or die("Can't send email!");; fclose($fd);
endif;
endwhile;
// Известить пользователя об успешной отправке
print sizeof($information)." informational newsletters
have been sent to $email!";
endif;
?>
В листинге 10.6 мы перебираем пары «ключ/значение» в цикле while и отправляем только те бюллетени, у которых значение равно у. Следует
помнить, что имена текстовых файлов должны соответствовать ключам массива
(site.txt, team.txt и events.txt). Имя файла строится динамически по ключу, после чего файл открывается по имени и его содержимое загружается в
переменную ($contents). Затем переменная $contents передается функции mail( ) в качестве параметра.
В следующем примере пользовательские данные сохраняются в текстовом файле.
Пример 5: сохранение пользовательских данных в текстовом файле
Пользовательские данные сохраняются в текстовом файле для последующего статистического анализа, поиска и т. д. — короче, любой
обработки по вашему усмотрению. В листинге 10.7, как и в предыдущих примерах, данные формы обрабатываются в одном сценарии.
Пользователю предлагается ввести четыре объекта данных: имя, адрес электронной почты, язык и профессию. Введенная информация
сохраняется в текстовом файле user_information.txt. Элементы данных разделяются символами «вертикальная черта» (|).
Листинг 10.7. Сохранение пользовательской информации в текстовом файле
// Создать форму
$form = "
";
// Заполнялась ли форма ранее? if ($seenform != "у") :
print "$form"; else :
$fd = fopen("useMnformation.txt", "a");
// Убедиться, что во введенных данных не встречается
// вертикальная черта.
$name = str_replace("|", "", $name);
$email = str_replace("|", "", $email);
// Построить строку с пользовательскими данными
$user_row = $name." ".$email."|".$language." ".$job."\n";
fwrite($fd, $user_row) or die("Could not write to file!");
fclose($fd);
print "Thank you for taking a moment to fill out our brief questionnaire!":
endif;
?>
Обратите внимание на фрагмент, в котором мы проверяем, что пользователь не включил в имя или адрес электронной почты символы
«вертикальная черта» (|). Функция str_replace( ) удаляет эти символы, заменяя их пустой строкой. Если бы это не было сделано,
пользовательские символы | нарушили бы структуру файла данных и существенно затруднили (а то и сделали невозможным) его правильную
обработку.
При работе с относительно малыми объемами информации вполне можно обойтись текстовыми файлами. Однако при большом количестве
пользователей или объеме сохраняемой информации для хранения и обработки данных, введенных в форме, лучше воспользоваться базой
данных. Эта тема подробно рассматривается в главе 11.
До настоящего момента предполагалось, что пользователь всегда вводит правильные данные и не действует злонамеренно. В высшей степени
оптимистичное предположение! В следующем разделе мы усовершенствуем рассмотренные примеры и организуем проверку целостности
данных форм. Проверка ошибок не только обеспечивает удаление неполной и неправильной информации, но и обеспечивает более
эффективный и удобный интерфейс.