_(Продолжение, начало см. в МК № 38-40, 42, 44, 46 (209-211, 213, 215, 217)). В качестве предисловия к сегодняшней статье мне хотелось бы подвести первые итоги нашей совместной деятельности, которая, должен отметить, оказалась очень даже продуктивной. С каждым днем мой бесплатный почтовый ящик принимает от трех до пяти читательских писем, большей частью благодарных. Из этого следует, что у вас все получается и вы недаром занялись изучением языка РНР. Я же, в свою очередь, покорный зову из «беседки» МК, всегда рад помочь :-).

Итак, итоги. Жесткий диск вашего компьютера обзавелся настроенным сервером, а ваша персональная база знаний — основами нового языка программирования. Все эти знания я небезосновательно решил применить для написания своего интернет-магазина. Почему именно ИМ? Да потому что Интернет содержит огромное количество статей о написании форумов, гостевых книг и прочей «живности» для вашего сайта — нужно только немного терпения для их поиска и изучения. Все они, увы, не отражают всех особенностей языка, к тому же в последнее время все реже адекватны практике. Интернет-магазин, напротив, содержит почти все основные приемы, применяемые в программировании (что ни фрейм — то новость :-)), и вполне может найти практическое применение в вашем предприятии. Я не говорю, что вам не нужна гостевая книга, форум или веб-интерфейс для вашей почты — просто, изучив приемы написания ИМ (работа с файлами, строками и массивами, передача и прием данных, cookies и сессии, upload файлов на сервер) и вооружившись справочником и словарем, вы вполне осилите написание любого сколь угодно сложного скрипта на РНР.

Кстати, насчет справочника. Электронный справочник по РНР представляет собой компилированную сборку HTML-файлов (расширение .chm, просматривается только при наличии на компьютере Internet Explorer’а версии 4 и выше) размером около 3 Мб. Справочник разработан группой создателей языка РНР, поэтому сомневаться в его объективности и правильности не приходится. Скачать его вы можете по адресу .

Единственный недостаток этого справочника — его англоязычность. И хотя для многих это перестало быть существенной проблемой, большинство все же предпочитает локализованные версии справочников. Но к сожалению, вынужден вас разочаровать — полной русской версии справочника по РНР я в Сети не нашел. Есть, конечно, кое-какие наметки (http://rusphp.chat.ru), но они не решают проблему локализации. Поэтому я предлагаю вам (да-да, именно вам!) принять посильное участие в разработке русскоязычного справочника по элементам языка РНР. Для этого вооружайтесь словарем и переводите, переводите, переводите… Нет, не бумагу :-), а каждую новую функцию из англоязычного справочника, с которой вы сталкиваетесь в процессе изучения языка. Все, что вы напереводите, присылайте мне — я все это соберу, откомпилирую и выложу на общедоступные сервера. Таким образом и вы сможете наследить в истории :-).

Теперь перейдем к делу. На прошлом занятии мы разобрались с левым фреймом интернет-магазина, сегодня же плавно переходим к центральному, а точнее, к связке левого и центрального фреймов. Почему к связке? Потому что центральный фрейм будет обрабатывать информацию, поступившую к нему из левого фрейма при нажатии в последнем на гиперссылку отдела. И здесь мы сразу сталкиваемся с новыми особенностями языка РНР — с функциями передачи и обработки данных.

Но для начала немного теории. Передача данных клиентом и прием данных с сервера при работе в Интернет осуществляются при помощи стандартизованного протокола HTTP (аббревиатура от английского HyperText Transfer Protocol, протокол передачи гипертекста). Каждый успешно завершенный цикл приема-передачи данных в HTTP называется транзакцией (transaction). Так как HTTP стандартизован (русскую спецификацию вы можете почитать на сайте http://www.helloworld.ru), все транзакции этого протокола имеют один общий формат. Каждый запрос клиента и ответ сервера состоит из трех частей: строки запроса (ответа), раздела заголовка и тела запроса.

Клиент инициализирует транзакцию примерно следующим образом:

1. Клиент устанавливает связь с сервером по назначенному номеру порта (по умолчанию 80). Затем клиент посылает запрос документа, указав HTTP-команду, называемую методом (об этом чуть позже), адрес документа и номер версии HTTP. Например, в запросе

GET /index.html HTTP/1.0

используется метод GET, которым с помощью версии 1.0 HTTP-протокола запрашивается документ index.html.

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

USER-AGENT: Mozilla/2.02Gold (WinNT; I) Accept: image/gif, image/jpeg

Заголовок должен заканчиваться пустой строкой.

3. Послав запрос и заголовки, клиент может отправить и дополнительные данные. Эти данные используются главным образом теми CGI-программами, которые применяют метод POST. Клиенты могут их использовать для помещения отредактированной страницы обратно на web-сервер.

Сервер отвечает на запросы клиента следующим образом:

1. Первая часть ответа сервера —строка состояния, содержащая три поля: версию HTTP, код состояния и описание. Поле версии содержит номер версии HTTP, которой данный сервер пользуется для передачи ответа. Код состояния — это трехразрядное число, выражающее результат обработки сервером запроса клиента. Описание, следующее за кодом состояния, представляет собой просто понятный для человека текст, поясняющий код состояния. Например, строка состояния

HTTP/1.0. 200 OK

говорит о том, что сервер для ответа использует версию HTTP 1.0 Код состояния 200 означает, что запрос клиента был успешным, и затребованные данные будут переданы после заголовков. Слово ОК, как мне кажется, понятно без комментариев :-).

2. После строки состояния сервер передает клиенту информацию заголовка, содержащую данные о самом сервере и затребованном документе. Пример HTTP-заголовка:

Date: Fri, 20 Mar 1999 08:17:58 GMT Server: NCSA/1.5.2 Last-modified: Mon, 17 Jun 1996 21:53:08 GMT Content-type: text/html Content-lenght: 2482

Как и в запросе, заголовок ответа завершает пустая строка.

3. Если запрос клиента успешен, то посылаются затребованные данные. Это может быть копия файла или результат выполнения CGI-программы. Если запрос клиента удовлетворить нельзя, передаются дополнительные данные в виде понятного для пользователя разъяснения причин, по которым сервер не смог выполнить данный запрос.

HTTP версии 1.0 поддерживает три типа методов запроса (напомню, что метод — это HTTP-команда, с которой начинается запрос клиента). Метод сообщает серверу о цели запроса и способе его реализации. Два основных метода запроса — это GET и POST. Существует также метод HEAD, который, в силу своей специфичности, редко используется при разработке страниц и программ — он запрашивает только заголовок ответа, не принимая более никаких данных, т.е. инициализирует неполную транзакцию. Это может быть полезно для определения времени создания страницы — клиент запросит только заголовок, что сократит время обработки запроса и снизит нагрузку на сервер.

Мы в своих программах будем пользоваться только методами GET и POST. Поэтому остановлюсь на их описании подробнее.

Команда GET, посылаемая серверу, в качестве своего аргумента должна содержать путь к файлу, который запрашивается у сервера, дополнительную информацию, которую этот файл должен обработать (в случае, если файл является CGI-программой) и версию HTTP-протокола, в соответствии с которой должен обработаться данный запрос. При этом имя файла и его параметры передаются в составе URL. В адресной строке браузера такой запрос будет выглядеть примерно так:

http://127.0.0.1/shop/central.phtml?otdel=3

Метод GET в данном случае в качестве своего аргумента принимает значение /central.phtml?otdel=3 и версию HTTP, указанную в установках браузера клиента. Имя файла и параметры строки запроса, которые ему передаются, по умолчанию разделяются знаком вопроса (?), после которого могут идти пары переменная=значение, разделенные знаком амперсанта (&). Количество пар переменная=значение и возможный размер значений переменных определяется типом сервера и в разных версиях может быть различным. Недостатком этого метода можно считать отсутствие секретности при передаче данных (запрос могут увидеть посторонние в адресной строке вашего браузера) и малый размер передаваемых значений.

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

При написании нашего ИМ мы будем использовать оба метода передачи данных в равной степени, но в разных ролях. В ссылках левого фрейма (а также в центральном и правом фреймах) используется метод GET, так как только с его помощью мы можем «засунуть» динамическую информацию в статическую страницу. Для обновления прайс-листа (для закачки его на сервер хостинг-провайдера) будет использоваться метод POST.

Но давайте же наконец займемся делом :-). В предыдущей статье мы разобрались с динамической генерацией ссылок на отделы нашего ИМ. Теперь же эти ссылки необходимо связать с центральным фреймом таким образом, чтобы при щелчке мышью на ту или иную ссылку в левом фрейме в центральном фрейме открывалось содержимое соответствующего отдела. Кстати, это содержимое неплохо бы создать :-). Открываем файл price.csv и дописываем в него продукцию:

Рис. 1

Продукт выбранного отдела в прайсе строится примерно по следующей схеме (разделители элементов, как вы помните, — точки с запятой): первый элемент — буква t — условное обозначение, показывающее, что перед нами товар; второй элемент — номер отдела, которому соответствует данный товар (этот номер является вторым элементом в обозначении отдела); третий элемент — порядковый номер продукта в отделе; четвертый и пятый элементы — название продукта и цена соответственно.

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

Рис. 2

Этот скрипт посредством метода GET получает запрос, извлекает из него значение переменной (номер отдела) и в зависимости от значения переменной загружает в тело страницы содержимое того или иного отдела. Для извлечения значения переменной из строки запроса, посланной методом GET, используется специальный массив $_GET (в версиях РНР до 4.1.0 использовали $HTTP_GET_VARS). Этот массив является ассоциативным, то есть доступ к его элементам мы можем получить, ссылаясь на имя значения, а не на его индекс. Именно этим мы и занимаемся :-).

Далее в скрипте проверяется наличие переменной отдела (если ее нет, значит, запрос не был послан — например, при первой загрузке страницы), открывается файл price.csv, из которого в цикле считываются значения названий продуктов и цены, соответствующие номеру запрошенного отдела. На основании этих данных генерируется форма, с помощью которой в дальнейшем выбранная продукция будет передаваться в корзину покупателя (в левый фрейм).

Вся эта фантазия :-) в работающем виде будет выглядеть примерно так:

Рис. 3

Естественно, никто не запрещает вам придать ИМ более привлекательный внешний вид (скажем, разместить элементы в таблице), но, как мы уже договаривались, для программиста главное — суть и работоспособность проекта, а не его оформление. Думаю, суть вы уже уловили :-).

(Продолжение следует)