HTML-формы позволяют передавать введенные пользователем данные на сервер, где их можно дополнительно обработать. Обслуживание форм выполняется в два этапа. Сначала форма должна быть представлена пользователю, который заполнит ее своими данными и затем отправит на сервер. У каждой формы есть целевая веб-страница, которая должна быть загружена для обработки данных, отправленных пользователем. Зачастую это тот же самый файл сценария, который генерирует форму. В этом случае PHP-код просто проверяет наличие данных в форме, чтобы определить, вызывать ли ему вновь сценарий для создания формы или начать обработку полученных данных.

Внимание! Урок устарел. Новые уроки по этой теме содержатся в курсе PHP для начинающих .

В большинстве случаев, отправка форм на сервер предполагает какую-то работу с базами данных. Например, операция поиска в базе данных – это необходимое действие для большинства разнообразных приложений, будь то поиск сообщений в форуме, пользователей или блога. В любом случае эта операция способна облегчить жизнь пользователя. Т.к. к данному моменту мы еще не познакомились с взаимодействием PHP и СУБД MySQL, то в данной статье мы рассмотрим простые примеры обработки форм, а главной задачей для меня является показать как происходит передача информации с помощью языка PHP.

Передача информации с помощью языка PHP

В данном разделе приведены основные сведения о том, как может осуществляться передача данных между веб-страницами. Определенная часть этой информации не относится исключительно к технологии PHP, а описывает взаимодействие средств PHP и HTML или касается самого протокола HTTP.

Отсутствие поддержки состояния в протоколе HTTP

Наиболее важная особенность функционирования любой технологии веб, о которой всегда следует помнить, состоит в том, что сам протокол HTTP характеризуется отсутствием поддержки состояний. Это означает, что каждый запрос HTTP (который в большинстве случаев сводится к требованию на получение и доставку отдельного ресурса, такого как HTML-страница, файл.jpg, таблица стилей и т.д.) является независимым от всех других запросов, не включает какую-либо информацию об идентификации клиента и не оставляет следа в памяти компьютера.

Даже если сайт спроектирован таким образом, что навигация, т.е. переход с одной страницы на другую, происходит строго в одном направлении (допустим, страница 1 ведет только к странице 2, которая ведет только к странице 3, и т.д.), средства поддержки протокола HTTP не имеют информации и не учитывают то, что пользователь, просматривающий страницу 2, обязательно должен был посетить перед этим страницу 1. Нельзя присвоить значение какой-либо переменной на странице 1 и надеяться на то, что оно будет импортировано на страницу 2 с помощью самого языка HTML. Код HTML может использоваться для отображения формы, и с помощью этого кода можно даже вводить информацию, но если не будут применяться некоторые дополнительные средства передачи введенной информации на другую страницу или в другую программу, то значение, присвоенное переменной, после перехода на другую страницу просто исчезнет.

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

Удобные возможности по передаче небольшого количества значений с данной конкретной страницы на любую другую отдельную страницу веб-сайта предоставляют формы HTML. Есть и другие способы поддержки состояния на протяжении многих просмотров страниц, характеризующиеся большей продолжительностью хранения данных, такие как cookie-файлы и сеансы, которые будут описаны в одной из следующих статей. А в этой статье рассматриваются в основном наиболее простые способы передачи информации между веб-страницами, в которых используются методы GET и POST в сочетании с протоколом HTTP для создания динамически формируемых страниц и обработки данных формы.

Параметры GET

Метод GET предусматривает передачу параметров с предыдущей страницы на следующую в составе строки запроса, которая представлена в формате универсального идентификатора ресурса URI. При использовании метода GET для обработки формы к URL, обозначенному с помощью атрибута action формы, после разделителя добавляется в виде вопросительного знака указанное имя (имена) и значение (значения) переменной, после чего вся эта строка передается обрабатывающему агенту (в данном случае веб-серверу).

Ниже приведен пример формы HTML, в которой используется метод GET (введите эту разметку и сохраните файл под именем sportselect.html):

Основы PHP

Выберите ваш любимый вид спорта

После того как пользователь сделает свой выбор и щелкнет на кнопке "Отправить", браузер соединит перечисленные ниже элементы в указанном порядке, без пробелов между элементами:

  • URL в кавычках после слова action (http://localhost/sports.php).
  • Вопросительный знак (?), обозначающий, что следующие символы составляют строку GET.
  • Переменная name, знак равенства (=) и соответствующий параметр value (value=Хоккей).
  • Амперсанд (&) и следующая за ним пара name=value (если таковая имеется).

Таким образом, браузер сформирует следующую строку URL:
http://localhost/sports.php?sport=Хоккей

Затем браузер перенаправляет полученную строку URL в пределах собственного пространства адресов в качестве нового запроса. Сценарий PHP, приведенный ниже (sports.php), в который передается указанная форма, осуществляет выборку значений переменных GET из последней части строки запроса, вставляет эти переменные и значения переменных в суперглобальный массив $_GET (который будет вскоре описан) и выполняет какие-то необходимые действия с этими значениями; в данном случае происходит вставка в текстовую строку.

Ниже приведен пример кода, в котором показан обработчик формы PHP для указанной выше формы HTML:

Любимый вид спорта

Ваш любимый вид спорта -

Обратите внимание на то, что значение, введенное в поле формы HTML с атрибутом name="sport" на предыдущей странице, теперь доступно в виде переменной PHP с именем $_GET["sport"]. Работу этого примера демонстрирует следующий рисунок:

Теперь необходимо объяснить, как именно можно получить доступ к значениям, передаваемым со страницы на страницу. В этой статье рассматриваются два основных метода передачи значений используемых в формах - GET и POST. Каждый метод имеет связанный с ним суперглобальный массив. Суперглобальные массивы описаны более подробно в статье "Переменные и константы". Отличительной особенностью суперглобальных массивов от других массивов является наличие префикса в имени в виде знака подчеркивания.

Обработчик форм получает доступ к каждому элементу, передаваемому с помощью метода GET, обращаясь к массиву $_GET, а к каждому элементу, передаваемому с помощью метода POST, обращаясь к массиву $_POST. Синтаксическая структура, применяемая для обращения к какому-либо элементу суперглобального массива, является простой и полностью единообразной:

$_array_name["index_name"]

Здесь index_name - это часть пары "имя-значение", относящаяся к имени (для метода GET), или имя поля формы HTML (для метода POST). В соответствии с предыдущим примером $_GET["sport"] указывает значение элемента select формы, имеющего имя "sport"; это значение передано с помощью операции GET, выполненной применительно к первоначальному файлу. В обработчике формы необходимо использовать массив, соответствующий методу, с помощью которого были переданы данные. В частности, в рассматриваемом примере значение $_POST["sport"] не определено, поскольку из первоначальной формы не были отправлены какие-либо данные с помощью метода POST.

Метод GET обработки форм обладает одним значительным преимуществом над методом POST - он фактически позволяет каждый раз формировать новую и соответствующую текущей ситуации строку запроса URL. После этого пользователи могут устанавливать закладку на данную страницу. С другой стороны, результаты передачи форм с помощью метода POST не могут быть отмечены закладками.

Только то, что желаемые функциональные возможности могут быть достигнуты с помощью параметров GET, не означает, что обязательно нужно использовать метод GET. Недостатки метода GET, которые обнаруживаются в большинстве типов обработки форм, являются столь существенными. В оригинальной рабочей спецификации HTML 4.0, опубликованной в 1997 году, этот метод не был рекомендован к использованию. Основные недостатки метода GET перечислены ниже:

  • Метод GET не применим для создания окон регистрации, поскольку имя пользователя и пароль полностью видны на экране, а также не исключена возможность сохранения этих данных в памяти браузера клиента в качестве информации о посещенной странице.
  • Каждая операция передачи данных по методу GET, включая сам набор данных, регистрируется в журнале веб-сервера.
  • В методе GET предусмотрено присваивание данных переменной среды сервера, поэтому длина URL ограничена. Возможно, вам доводилось видеть, как выглядят очень длинные URL, переданные с помощью метода GET, и действительно, вряд ли кому-то захочется передавать с помощью этого метода фрагмент текста в формате HTML, состоящего из 300 слов.

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

Параметры POST

В настоящее время предпочтительным методом отправки данных формы является POST (особенно при случаях, в которых осуществление действий приводит к постоянным изменениям, таких как ввод информации в базу данных). Набор данных формы включается в тело формы при перенаправлении формы к обрабатывающему агенту (в данном случае к интерпретатору PHP). Строка URL не претерпевает каких-либо видимых изменений, отражающих разнообразие передаваемых данных.

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

Первым и наиболее важным правилом программирования, особенно программирования для сети, является следующее:
Никогда не доверять входным данным.

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

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

Чтобы изменить способ передачи данных в предыдущем примере, нужно внести следующие изменения:

...

Работа с несколькими значениями

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

" method="post">
Выберите ваших любимых питомцев

Выбраны животные: "; foreach ($animal as $a) { echo "".htmlentities($a)." "; } } ?>

Эта форма позволяет пользователю выбрать любимых питомцев. В данном примере пользователь может пометить сразу несколько флажков. Значит, при обработке данных формы в PHP-сценарии необходимо предусмотреть возможность получить доступ к нескольким значениям по одному имени. Мы поместили пару квадратных скобок () после имени в атрибуте name, чтобы иметь возможность отправлять несколько вариантов выбора в виде массива. Если бы квадратные скобки были опущены, и пользователь пометил бы несколько флажков, его выбор был бы замещен последним отмеченным флажком. Поместив квадратные скобки после имени, мы указали, что значения должны храниться в виде массива.

В обработчике массив сохраняется в переменную $animal и перечисляется с помощью цикла foreach, как обычный массив.

Валидация формы и форматирование переменных формы

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

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

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

В примере ниже показан способ обработки формы, включающий валидацию на стороне сервера и обработку на той же странице формы:

Основы PHP

" method="post">
Контактная информация " class="">
" class="">

В этом примере используется функция filter_var() которая осуществляет проверку переменной с использованием фильтра и принимает два параметра - исходную строку и константу, указывающую на тип фильтра. Кроме валидации email-адресов (FILTER_VALIDATE_EMAIL) эта функция поддерживает следующие константы: FILTER_VALIDATE_URL - проверяет значение на корректность URL (например,), FILTER_VALIDATE_IP - проверяет значение на корректность IP-адресов, FILTER_VALIDATE_REGEXP - проверяет значение на корректность синтаксису регулярного выражения и несколько других констант, являющихся альтернативами функций is_bool(), is_float(), is_int() и т.п.

Клиенты браузера могут отправлять информацию на веб-сервер.

Прежде чем браузер отправит информацию, он кодирует ее, используя схему, называемую кодировкой URL. В этой схеме пары имя / значение объединяются с равными знаками, а разные пары разделяются амперсандом.

Name1=value1&name2=value2&name3=value3

Пробелы удаляются и заменяются символом +, и любые другие неалфанумерные символы заменяются шестнадцатеричными значениями. После того, как информация закодирована, она отправляется на сервер.

Метод GET

Метод GET отправляет закодированную пользовательскую информацию, добавленную к запросу страницы. Страницы и кодированной информации отделены друг от друга? знаком вопроса.

http://www.test.com/index.htm?name1=value1&name2=value2

  • Метод GET создает длинную строку, которая отображается в ваших журналах сервера, в поле «Расположение» браузера.
  • Метод GET ограничивается отправить ДО только 1024 символов.
  • Никогда не используйте метод GET, если у вас есть пароль или другая конфиденциальная информация для отправки на сервер.
  • GET не может быть использован для передачи двоичных данных, например, изображения или текстовые документы, на сервер.
  • Доступ к данным, отправленным методом GET, можно получить с помощью переменной окружения QUERY_STRING.
  • PHP предоставляет ассоциативный массив $ _GET для доступа ко всей отправляемой информации с использованием метода GET.

if($_GET["name"] || $_GET["age"]) { echo "Welcome ". $_GET["name"]; echo "You are ". $_GET["age"]. " years old."; exit(); }

Name: Age:

Метод POST

Метод POST передает информацию через HTTP-заголовки. Информация кодируется, как описано в случае метода GET , и помещается в заголовок QUERY_STRING .

  • Метод POST не имеет ограничений на размер данных, которые необходимо отправить.
  • Метод POST может использоваться для отправки ASCII, а также двоичных данных.
  • Данные, отправленные методом POST, проходят через HTTP-заголовок, поэтому безопасность зависит от протокола HTTP. Используя Secure HTTP, вы можете убедиться, что ваша информация защищена.
  • PHP предоставляет ассоциативный массив $_POST для доступа ко всей отправляемой информации с использованием метода POST.

Попробуйте следующий пример, поместив исходный код в скрипт test.php .

if($_POST["name"] || $_POST["age"]) { if (preg_match("[^A-Za-z"-]",$_POST["name"])) { die ("invalid name and name should be alpha"); } echo "Welcome ". $_POST["name"]; echo "You are ". $_POST["age"]. " years old."; exit(); }

Name: Age:

Переменная $_REQUEST

Переменная PHP $_REQUEST содержит содержимое как $_GET , $_POST , так и $_COOKIE . Мы обсудим переменную $_COOKIE , когда мы расскажем о файлах cookie.

Переменная PHP $_REQUEST может использоваться для получения результата из данных формы, отправленных с использованием методов GET и POST.

PHP, в настоящее время, – один из наиболее популярных языков для реализации веб-приложений. Данный курс посвящен изучению его основ. Акцент делается на практическое применение полученных навыков.

Язык PHP был создан для решения конкретной практической задачи в среде интернет (какой именно можно узнать, прочитав первую лекцию курса). Мы тоже постараемся не отвлекаться слишком сильно на теоретические рассуждения, и будем стремиться к решению какой-нибудь конкретной задачи в каждой из лекций. Большинство примеров взяты из реально существующей системы: виртуального музея истории информатики. Первая часть курса посвящена изучению основ синтаксиса и управляющим конструкциям. После этого рассматривается технология клиент-сервер, как основная сфера приложения языка PHP. Затем переходим к изучению наиболее полезных на наш взгляд встроенных функций и решению с их помощью практических задач. Хотя объектная модель в языке PHP не самая богатая, ее принципиальное наличие позволяет естественным образом описывать объектные модели данных. В качестве базовой модели будет рассмотрена модель документа виртуального музея информатики. После этого будет рассмотрен ряд прикладных аспектов: работа с файловой системой, с БД, строками, сессиями, DOM XML - все это позволит рассмотреть ключевые задачи практического использования языка.

Как видно из приведенной таблицы, сервер Apache занимает лидирующие позиции. Все, что мы когда-либо будем говорить о web-серверах, ориентировано на Apache, если не указано иное. О том, как установить его на свой компьютер, мы уже рассказывали в самой первой лекции. А теперь, как было обещано, обратимся к протоколу HTTP.

Протокол HTTP и способы передачи данных на сервер

Internet построен по многоуровневому принципу, от физического уровня, связанного с физическими аспектами передачи двоичной информации, и до прикладного уровня, обеспечивающего интерфейс между пользователем и сетью.

HTTP (HyperText Transfer Protocol, протокол передачи гипертекста) – это протокол прикладного уровня, разработанный для обмена гипертекстовой информацией в Internet.

HTTP предоставляет набор методов для указания целей запроса, отправляемого серверу. Эти методы основаны на дисциплине ссылок, где для указания ресурса, к которому должен быть применен данный метод, используется универсальный идентификатор ресурсов (Universal Resource Identifier) в виде местонахождения ресурса (Universal Resource Locator, URL) или в виде его универсального имени (Universal Resource Name, URN).

Сообщения по сети при использовании протокола HTTP передаются в формате, схожем с форматом почтового сообщения Internet (RFC-822) или с форматом сообщений MIME (Multipurpose Internet Mail Exchange).

HTTP используется для коммуникаций между различными пользовательскими программами и программами-шлюзами, предоставляющими доступ к существующим Internet-протоколам, таким как SMTP (протокол электронной почты), NNTP (протокол передачи новостей), FTP (протокол передачи файлов), Gopher и WAIS. HTTP разработан для того, чтобы позволять таким шлюзам через промежуточные программы-серверы (proxy) передавать данные без потерь.

Протокол реализует принцип запрос/ответ. Запрашивающая программа – клиент инициирует взаимодействие с отвечающей программой – сервером и посылает запрос, содержащий:

Метод доступа;

Адрес URI;

Версию протокола;

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

Ответ сервера содержит:

Строку состояния, в которую входит версия протокола и код возврата (успех или ошибка);

Сообщение (в форме, похожей на MIME), в которое входит информация сервера, метаинформация (т.е. информация о содержании сообщения) и тело сообщения.

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

Давайте рассмотрим более подробно, в какой форме отправляются запросы на сервер.

Форма запроса клиента

Клиент отсылает серверу запрос в одной из двух форм: в полной или сокращенной. Запрос в первой форме называется соответственно полным запросом, а во второй форме – простым запросом.

Простой запрос содержит метод доступа и адрес ресурса. Формально это можно записать так:

<Простой-Запрос> := <Метод> <символ пробел>
<Запрашиваемый-URI> <символ новой строки>

В качестве метода могут быть указаны GET, POST, HEAD, PUT, DELETE и другие. О наиболее распространенных из них мы поговорим немного позже. В качестве запрашиваемого URI чаще всего используется URL-адрес ресурса.

Пример простого запроса:

GET http://phpbook.info/

Здесь GET – это метод доступа, т.е. метод, который должен быть применен к запрашиваемому ресурсу, а http://phpbook.info/ – это URL-адрес запрашиваемого ресурса.

Полный запрос содержит строку состояния, несколько заголовков (заголовок запроса, общий заголовок или заголовок содержания) и, возможно, тело запроса. Формально общий вид полного запроса можно записать так:

<Полный запрос> := <Строка Состояния>
(<Общий заголовок>|<Заголовок запроса>|
<Заголовок содержания>)
<символ новой строки>
[<содержание запроса>]

Квадратные скобки здесь обозначают необязательные элементы заголовка, через вертикальную черту перечислены альтернативные варианты. Элемент <Строка состояния> содержит метод запроса и URI ресурса (как и простой запрос) и, кроме того, используемую версию протокола HTTP. Например, для вызова внешней программы можно задействовать следующую строку состояния:

POST http://phpbook.info/cgi-bin/test HTTP/1.0

В данном случае используется метод POST и протокол HTTP версии 1.0.

В обеих формах запроса важное место занимает URI запрашиваемого ресурса. Чаще всего URI используется в виде URL-адреса ресурса. При обращении к серверу можно применять как полную форму URL, так и упрощенную.

Полная форма содержит тип протокола доступа, адрес сервера ресурса и адрес ресурса на сервере (рисунок 4.2).

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


Рис. 4.2. Полная форма URL

Методы

Как уже говорилось, любой запрос клиента к серверу должен начинаться с указания метода. Метод сообщает о цели запроса клиента. Протокол HTTP поддерживает достаточно много методов, но реально используются только три: POST, GET и HEAD. Метод GET позволяет получить любые данные, идентифицированные с помощью URI в запросе ресурса. Если URI указывает на программу, то возвращается результат работы программы, а не ее текст (если, конечно, текст не есть результат ее работы). Дополнительная информация, необходимая для обработки запроса, встраивается в сам запрос (в строку статуса). При использовании метода GET в поле тела ресурса возвращается собственно затребованная информация (текст HTML-документа, например).

Существует разновидность метода GET – условный GET. Этот метод сообщает серверу о том, что на запрос нужно ответить, только если выполнено условие, содержащееся в поле if-Modified-Since заголовка запроса. Если говорить более точно, то тело ресурса передается в ответ на запрос, если этот ресурс изменялся после даты, указанной в if-Modified-Since.

Метод HEAD аналогичен методу GET, только не возвращает тело ресурса и не имеет условного аналога. Метод HEAD используют для получения информации о ресурсе. Это может пригодиться, например, при решении задачи тестирования гипертекстовых ссылок.

Метод POST разработан для передачи на сервер такой информации, как аннотации ресурсов, новостные и почтовые сообщения, данные для добавления в базу данных, т.е. для передачи информации большого объема и достаточно важной. В отличие от методов GET и HEAD, в POST передается тело ресурса, которое и является информацией, получаемой из полей форм или других источников ввода.

До сих пор мы только теоретизировали, знакомились с основными понятиями. Теперь пора научиться использовать все это на практике. Далее в лекции мы рассмотрим, как посылать запросы серверу и как обрабатывать его ответы.

Использование HTML-форм для передачи данных на сервер

Как передавать данные серверу? Для этого в языке HTML есть специальная конструкция – формы. Формы предназначены для того чтобы получать от пользователя информацию. Например, вам нужно знать логин и пароль пользователя для того, чтобы определить, на какие страницы сайта его можно допускать. Или вам необходимы личные данные пользователя, чтобы была возможность с ним связаться. Формы как раз и применяются для ввода такой информации. В них можно вводить текст или выбирать подходящие варианты из списка. Данные, записанные в форму, отправляются для обработки специальной программе (например, скрипту на PHP) на сервере. В зависимости от введенных пользователем данных эта программа может формировать различные web-страницы, отправлять запросы к базе данных, запускать различные приложения и т.п.

Разберемся с синтаксисом HTML-форм. Возможно, многие с ним знакомы, но мы все же повторим основные моменты, поскольку это важно.

Итак, для создания формы в языке HTML используется тег FORM. Внутри него находится одна или несколько команд INPUT. С помощью атрибутов action и method тега FORM задаются имя программы, которая будет обрабатывать данные формы, и метод запроса, соответственно. Команда INPUT определяет тип и различные характеристики запрашиваемой информации. Отправка данных формы происходит после нажатия кнопки input типа submit. Создадим форму для регистрации участников заочной школы программирования.

После обработки браузером этот файл будет выглядеть примерно так:


Рис. 4.3. Пример html-формы

Вот так создаются и выглядят HTML-формы. Будем считать, что мы научились или вспомнили, как их создавать. Как мы видим, в форме можно указывать метод передачи данных. Посмотрим, что будет происходить, если указать метод GET или POST, и в чем будет разница.

Для метода GET

При отправке данных формы с помощью метода GET содержимое формы добавляется к URL после знака вопроса в виде пар имя=значения, объединенных с помощью амперсанта &:

action?name1=value1&name2=value2&name3=value3

Здесь action – это URL-адрес программы, которая должна обрабатывать форму (это либо программа, заданная в атрибуте action тега form, либо сама текущая программа, если этот атрибут опущен). Имена name1, name2, name3 соответствуют именам элементов формы, а value1, value2, value3 – значениям этих элементов. Все специальные символы, включая = и &, в именах или значениях этих параметров будут опущены. Поэтому не стоит использовать в названиях или значениях элементов формы эти символы и символы кириллицы в идентификаторах.

Если в поле для ввода ввести какой-нибудь служебный символ, то он будет передан в его шестнадцатеричном коде, например, символ $ заменится на %24. Так же передаются и русские буквы.

Для полей ввода текста и пароля (это элементы input с атрибутом type=text и type=password), значением будет то, что введет пользователь. Если пользователь ничего не вводит в такое поле, то в строке запроса будет присутствовать элемент name=, где name соответствует имени этого элемента формы.

Для кнопок типа checkbox и radio button значение value определяется атрибутом VALUE в том случае, когда кнопка отмечена. Не отмеченные кнопки при составлении строки запроса игнорируются целиком. Несколько кнопок типа checkbox могут иметь один атрибут NAME (и различные VALUE), если это необходимо. Кнопки типа radio button предназначены для одного из всех предложенных вариантов и поэтому должны иметь одинаковый атрибут NAME и различные атрибуты VALUE.

В принципе создавать HTML-форму для передачи данных методом GET не обязательно. Можно просто добавить в строку URL нужные переменные и их значения.

http://phpbook.info/test.php?id=10&user=pit

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

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

Для метода POST

Содержимое формы кодируется точно так же, как для метода GET (см. выше), но вместо добавления строки к URL содержимое запроса посылается блоком данных как часть операции POST. Если присутствует атрибут ACTION, то значение URL, которое там находится, определяет, куда посылать этот блок данных. Этот метод, как уже отмечалось, рекомендуется для передачи больших по объему блоков данных.

Информация, введенная пользователем и отправленная серверу с помощью метода POST, подается на стандартный ввод программе, указанной в атрибуте action, или текущему скрипту, если этот атрибут опущен. Длина посылаемого файла передается в переменной окружения CONTENT_LENGTH, а тип данных – в переменной CONTENT_TYPE.

Передать данные методом POST можно только с помощью HTML-формы, поскольку данные передаются в теле запроса, а не в заголовке, как в GET. Соответственно и изменить значение параметров можно, только изменив значение, введенное в форму. При использовании POST пользователь не видит передаваемые серверу данные.

Основное преимущество POST запросов – это их большая безопасность и функциональность по сравнению с GET-запросами. Поэтому метод POST чаще используют для передачи важной информации, а также информации большого объема. Тем не менее не стоит целиком полагаться на безопасность этого механизма, поскольку данные POST запроса также можно подделать, например создав html-файл на своей машине и заполнив его нужными данными. Кроме того, не все клиенты могут применять метод POST, что ограничивает варианты его использования.

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

REMOTE_ADDR – IP-адрес хоста (компьютера), отправляющего запрос;

REMOTE_HOST – имя хоста, с которого отправлен запрос;

HTTP_REFERER – адрес страницы, ссылающейся на текущий скрипт;

REQUEST_METHOD – метод, который был использован при отправке запроса;

QUERY_STRING – информация, находящаяся в URL после знака вопроса;

SCRIPT_NAME – виртуальный путь к программе, которая должна выполняться;

HTTP_USER_AGENT – информация о браузере, который использует клиент

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

Внутри PHP-скрипта имеется несколько способов получения доступа к данным, переданным клиентом по протоколу HTTP. До версии PHP 4.1.0 доступ к таким данным осуществлялся по именам переданных переменных (напомним, что данные передаются в виде пар «имя переменной, символ «=», значение переменной»). Таким образом, если, например, было передано first_name=Nina, то внутри скрипта появлялась переменная $first_name со значением Nina. Если требовалось различать, каким методом были переданы данные, то использовались ассоциативные массивы $HTTP_POST_VARS и $HTTP_GET_VARS, ключами которых являлись имена переданных переменных, а значениями – соответственно значения этих переменных. Таким образом, если пара first_name=Nina передана методом GET, то $HTTP_GET_VARS["first_name"]="Nina".

Использовать в программе имена переданных переменных напрямую небезопасно. Поэтому было решено начиная с PHP 4.1.0 задействовать для обращения к переменным, переданным с помощью HTTP-запросов, специальный массив – $_REQUEST. Этот массив содержит данные, переданные методами POST и GET, а также с помощью HTTP cookies. Это суперглобальный ассоциативный массив, т.е. его значения можно получить в любом месте программы, используя в качестве ключа имя соответствующей переменной (элемента формы).

Пример 4.2. Допустим, мы создали форму для регистрации участников заочной школы программирования, как в приведенном выше примере. Тогда в файле 1.php, обрабатывающем эту форму, можно написать следующее:

$str = "Здравствуйте,
".$_REQUEST["first_name"]. "
".$_REQUEST["last_name"]."!
";
$str .="Вы выбрали для изучения курс по
".$_REQUEST["kurs"];
echo $str;
?>

Тогда, если в форму мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, на экране браузера получим такое сообщение:

Здравствуйте, Вася Петров!

После введения массива $_REQUEST массивы $HTTP_POST_VARS и $HTTP_GET_VARS для однородности были переименованы в $_POST и $_GET соответственно, но сами они из обихода не исчезли из соображений совместимости с предыдущими версиями PHP. В отличие от своих предшественников, массивы $_POST и $_GET стали суперглобальными, т.е. доступными напрямую и внутри функций и методов.

Приведем пример использования этих массивов. Допустим, нам нужно обработать форму, содержащую элементы ввода с именами first_name, last_name, kurs (например, форму form.html, приведенную выше). Данные были переданы методом POST, и данные, переданные другими методами, мы обрабатывать не хотим. Это можно сделать следующим образом:

$str = "Здравствуйте,
".$_POST ["first_name"]."
".$_POST ["last_name"] ."!
";
$str .= "Вы выбрали для изучения курс по ".
$_POST["kurs"];
echo $str;
?>

Тогда на экране браузера, если мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, увидим сообщение, как в предыдущем примере:

Здравствуйте, Вася Петров!
Вы выбрали для изучения курс по PHP

Для того чтобы сохранить возможность обработки скриптов более ранних версий, чем PHP 4.1.0, была введена директива register_globals, разрешающая или запрещающая доступ к переменным непосредственно по их именам. Если в файле настроек PHP параметр register_globals=On, то к переменным, переданным серверу методами GET и POST, можно обращаться просто по их именам (т.е. можно писать $first_name). Если же register_globals=Off, то нужно писать $_REQUEST["first_name"] или $_POST["first_name"], $_GET["first_name"], $HTTP_POST_VARS["first_name"], $HTTP_GET_VARS["first_name"]. С точки зрения безопасности эту директиву лучше отключать (т.е. register_globals=Off). При включенной директиве register_globals перечисленные выше массивы также будут содержать данные, переданные клиентом.

Иногда возникает необходимость узнать значение какой-либо переменной окружения, например метод, использовавшийся при передаче запроса или IP-адрес компьютера, отправившего запрос. Получить такую информацию можно с помощью функции getenv(). Она возвращает значение переменной окружения, имя которой передано ей в качестве параметра.

getenv("REQUEST_METHOD");
// возвратит использованный метод
echo getenv ("REMOTE_ADDR");
// выведет IP-адрес пользователя,
// пославшего запрос
?>

Как мы уже говорили, если используется метод GET, то данные передаются добавлением строки запроса в виде пар «имя_переменной=значение к URL-адресу ресурса». Все, что записано в URL после знака вопроса, можно получить с помощью команды

getenv("QUERY_STRING");

Благодаря этому можно по методу GET передавать данные в каком-нибудь другом виде. Например, указывать только значения нескольких параметров через знак плюс, а в скрипте разбирать строку запроса на части или можно передавать значение всего одного параметра. В этом случае в массиве $_GET появится пустой элемент с ключом, равным этому значению (всей строке запроса), причем символ «+», встретившийся в строке запроса, будет заменен на подчеркивание «_».

Методом POST данные передаются только с помощью форм, и пользователь (клиент) не видит, какие именно данные отправляются серверу. Чтобы их увидеть, хакер должен подменить нашу форму своей. Тогда сервер отправит результаты обработки неправильной формы не туда, куда нужно. Чтобы этого избежать, можно проверять адрес страницы, с которой были посланы данные. Это можно сделать опять же с помощью функции getenv():

getenv("HTTP_REFERER");

Теперь самое время решить задачу, сформулированную в начале лекции.

Пример обработки запроса с помощью PHP

Напомним, в чем состояла задача, и уточним ее формулировку. Нужно написать форму для регистрации участников заочной школы программирования и после регистрации отправить участнику сообщение. Мы назвали это сообщение универсальным письмом, но оно будет немного отличаться от того письма, которое мы составили на предыдущей лекции. Здесь мы также не будем отправлять что-либо по электронной почте, дабы не уподобляться спамерам, а просто сгенерируем это сообщение и выведем его на экран браузера. Начальный вариант формы регистрации мы уже приводили выше. Изменим его таким образом, чтобы каждый регистрирующийся мог выбрать сколько угодно курсов для посещения, и не будем подтверждать получение регистрационной формы.

Здесь все достаточно просто и понятно. Единственное, что можно отметить, – это способ передачи значений элемента checkbox. Когда мы пишем в имени элемента kurs, это значит, что первый отмеченный элемент checkbox будет записан в первый элемент массива kurs, второй отмеченный checkbox – во второй элемент массива и т.д. Можно, конечно, просто дать разные имена элементам checkbox, но это усложнит обработку данных, если курсов будет много.

Скрипт, который все это будет разбирать и обрабатывать, называется 1.php (форма ссылается именно на этот файл, что записано в ее атрибуте action). По умолчанию используется для передачи метод GET, но мы указали POST. По полученным сведениям от зарегистрировавшегося человека, скрипт генерирует соответствующее сообщение. Если человек выбрал какие-то курсы, то ему выводится сообщение о времени их проведения и о лекторах, которые их читают. Если человек ничего не выбрал, то выводится сообщение о следующем собрании заочной школы программистов (ЗШП).

Итак, в прошлом уроке мы вспоминали о том, как происходит работа пользователя с сайтом. Их общение происходит в форме запрос-ответ. Пользователь отправляет в запросе какие-то данные, а сервер возвращает какой-либо ответ, в зависимости от этих данных.

Он переходит по ней и прекрасно себя чувствует, потому что всё уже введено за него.

Однако, параметры в адресной строке – это не всегда уместно. Например, когда в параметрах содержится какая-то конфиденциальная информация: пароль, пин-код. И любой мимо проходящий человек может её увидеть. Как в такой ситуации быть? Использовать POST-запросы!

Что это такое? Да всё тот же запрос от клиента к серверу, только параметры передаются внутри тела запроса, а не в адресной строке. И увидеть их просто так не получится.

Что за тело запроса? Ну, это просто данные, которые передаются на сервер. При этом они скрыты от лишних глаз.

Чтобы отправить POST-запрос нужно в HTML-форме задать для атрибута method значение POST.

курса PHP для начинающих .

Данные, отправленные с помощью POST-запроса доступны в PHP в суперглобальном массиве $_POST .

Давайте выведем переданные скриптом выше значения login и password. Для этого в файл login.php положим следующий код:

Код доступен только после покупки курса PHP для начинающих .

Откройте теперь форму, введите в неё значения и нажмите кнопку «Войти».
Вы увидите введенные вами в форме данные, при этом они будут отсутствовать в адресной строке. Вуаля! Теперь никто не подсмотрит ваш пароль в адресной строке.

Как увидеть тело POST-запроса

Чтобы увидеть данные POST-запроса в браузере, в Google Chrome нужно перейти в режим разработчика. Нажмите клавишу F12, находясь в окне браузера. После этого вы увидите панель разработчика.

Перейдите во вкладку Network, а затем установите галочку напротив пункта Preserve log.

Теперь вернитесь на форму, и снова введите данные, после чего нажмите на кнопку «Войти».

Одновременно с тем, как вы нажмете на кнопку входа, вы увидите в панели разработчика запрос на login.php.

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

Нас здесь интересует вкладка Headers. Перейдите в неё, и прокрутите содержимое в самый низ. Здесь вы увидите те данные, что браузер отправил на сервер.

Заключение

Вот так и работают POST-запросы под капотом. Используют их всегда, когда не нужно отображать детали запроса в адресной строке. Хорошие примеры: форма авторизации, ввод данных о кредитной карте. Такими данными лучше в адресной строке не светить.

А сейчас - немного нестандартное домашнее задание =)

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

Содержимое формы кодируется точно так же, как для метода GET (см. выше), но вместо добавления строки кURL содержимое запроса посылается блоком данных как часть операцииPOST . Если присутствует атрибутACTION, то значениеURL , которое там находится, определяет, куда посылать этот блок данных. Этот метод, как уже отмечалось, рекомендуется для передачи больших по объему блоков данных.

Информация, введенная пользователем и отправленная серверу с помощью методаPOST , подается на стандартный ввод программе, указанной в атрибутеaction , или текущему скрипту, если этот атрибут опущен. Длина посылаемого файла передается впеременной окружения CONTENT_LENGTH, а тип данных – в переменнойCONTENT_TYPE.

Передать данные методом POST можно только с помощьюHTML-формы , поскольку данные передаются в теле запроса, а не в заголовке, как вGET . Соответственно и изменить значение параметров можно, только изменив значение, введенное в форму. При использованииPOST пользователь не видит передаваемыесерверу данные.

Основное преимущество POST запросов – это их большая безопасность и функциональность по сравнению с GET-запросами. Поэтому методPOST чаще используют для передачи важной информации, а также информации большого объема. Тем не менее не стоит целиком полагаться на безопасность этого механизма, поскольку данныеPOST запроса также можно подделать, например создав html-файл на своей машине и заполнив его нужными данными. Кроме того, не всеклиенты могут применять методPOST , что ограничивает варианты его использования.

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

    REMOTE_ADDR – IP-адрес хоста (компьютера), отправляющего запрос;

    REMOTE_HOST – имя хоста, с которого отправлен запрос;

    HTTP_REFERER – адрес страницы, ссылающейся на текущий скрипт;

    REQUEST_METHOD – метод, который был использован при отправке запроса;

    QUERY_STRING – информация, находящаяся в URL после знака вопроса;

    SCRIPT_NAME – виртуальный путь к программе, которая должна выполняться;

    HTTP_USER_AGENT – информация о браузере, который использует клиент

Обработка запросов с помощью php

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

Внутри PHP-скрипта имеется несколько способов получения доступа к данным, переданным клиентом по протоколуHTTP . До версии PHP 4.1.0 доступ к таким данным осуществлялся по именам переданных переменных (напомним, что данные передаются в виде пар «имя переменной, символ «=», значение переменной»). Таким образом, если, например, было переданоfirst_name=Nina, то внутри скрипта появлялась переменная$first_nameсо значениемNina. Если требовалось различать, каким методом были переданы данные, то использовались ассоциативные массивы$HTTP_POST_VARS и$HTTP_GET_VARS , ключами которых являлись имена переданных переменных, а значениями – соответственно значения этих переменных. Таким образом, если параfirst_name=Ninaпередана методомGET , то$HTTP_GET_VARS["first_name"]="Nina".

Использовать в программе имена переданных переменных напрямую небезопасно. Поэтому было решено начиная с PHP 4.1.0 задействовать для обращения к переменным, переданным с помощью HTTP-запросов, специальный массив – $_REQUEST . Этот массив содержит данные, переданные методамиPOST иGET , а также с помощьюHTTP cookies. Это суперглобальный ассоциативный массив, т.е. его значения можно получить в любом месте программы, используя в качестве ключа имя соответствующей переменной (элемента формы).

Пример 4.2. Допустим, мы создали форму для регистрации участников заочной школы программирования, как в приведенном выше примере. Тогда в файле1.php, обрабатывающем эту форму, можно написать следующее:

$str = "Здравствуйте,

".$_REQUEST["first_name"]. "

".$_REQUEST["last_name"]."!
";

$str .="Вы выбрали для изучения курс по

".$_REQUEST["kurs"];

Пример 4.2. Файл 1.php, обрабатывающий форму form.html (html , txt )

Тогда, если в форму мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, на экране браузера получим такое сообщение:

Здравствуйте, Вася Петров!

После введения массива $_REQUEST массивы$HTTP_POST_VARS и$HTTP_GET_VARS для однородности были переименованы в$_POST и$_GET соответственно, но сами они из обихода не исчезли из соображений совместимости с предыдущими версиями PHP. В отличие от своих предшественников, массивы$_POST и$_GET стали суперглобальными, т.е. доступными напрямую и внутри функций и методов.

Приведем пример использования этих массивов. Допустим, нам нужно обработать форму, содержащую элементы ввода с именами first_name,last_name,kurs(например, формуform.html, приведенную выше). Данные были переданы методомPOST , и данные, переданные другими методами, мы обрабатывать не хотим. Это можно сделать следующим образом:

$str = "Здравствуйте,

".$_POST ["first_name"]."

".$_POST ["last_name"] ."!
";

$str .= "Вы выбрали для изучения курс по ".

Тогда на экране браузера, если мы ввели имя «Вася», фамилию «Петров» и выбрали среди всех курсов курс по PHP, увидим сообщение, как в предыдущем примере:

Здравствуйте, Вася Петров!

Вы выбрали для изучения курс по PHP

Для того чтобы сохранить возможность обработки скриптов более ранних версий, чем PHP 4.1.0, была введена директива register_globals , разрешающая или запрещающая доступ к переменным непосредственно по их именам. Если в файле настроек PHP параметрregister_globals=On, то к переменным, переданнымсерверу методамиGET иPOST , можно обращаться просто по их именам (т.е. можно писать$first_name). Если же register_globals=Off, то нужно писать $_REQUEST["first_name"] или $_POST["first_name"], $_GET["first_name"], $HTTP_POST_VARS["first_name"], $HTTP_GET_VARS["first_name"]. С точки зрения безопасности эту директиву лучше отключать (т.е.register_globals=Off). При включенной директивеregister_globals перечисленные выше массивы также будут содержать данные, переданныеклиентом .

Иногда возникает необходимость узнать значение какой-либо переменной окружения , например метод, использовавшийся при передаче запроса или IP-адрес компьютера, отправившего запрос. Получить такую информацию можно с помощью функцииgetenv() . Она возвращает значениепеременной окружения , имя которой передано ей в качестве параметра.

getenv("REQUEST_METHOD");

// возвратит использованный метод

echo getenv ("REMOTE_ADDR");

// выведет IP-адрес пользователя,

// пославшего запрос

Пример 4.3. Использование функции getenv() (html , txt )

Как мы уже говорили, если используется метод GET , то данные передаются добавлением строки запроса в виде пар «имя_переменной=значение кURL -адресу ресурса». Все, что записано вURL после знака вопроса, можно получить с помощью команды

getenv("QUERY_STRING");

Благодаря этому можно по методу GET передавать данные в каком-нибудь другом виде. Например, указывать только значения нескольких параметров через знак плюс, а в скрипте разбирать строку запроса на части или можно передавать значение всего одного параметра. В этом случае в массиве$_GET появится пустой элемент с ключом, равным этому значению (всей строке запроса), причем символ «+», встретившийся в строке запроса, будет заменен на подчеркивание «_».

Методом POST данные передаются только с помощью форм, и пользователь (клиент ) не видит, какие именно данные отправляютсясерверу . Чтобы их увидеть, хакер должен подменить нашу форму своей. Тогдасервер отправит результаты обработки неправильной формы не туда, куда нужно. Чтобы этого избежать, можно проверять адрес страницы, с которой были посланы данные. Это можно сделать опять же с помощью функцииgetenv() :

getenv("HTTP_REFERER");

Теперь самое время решить задачу, сформулированную в начале лекции.


Close