HTTP взаимодействие
Программировать на PHP можно и без знания протокола HTTP. Но для решения ряда задач нужно знать, как именно работает веб-сервер. Ведь PHP — это в первую очередь серверный язык программирования.
Протокол HTTP очень прост и состоит из двух частей:
- Заголовков запроса/ответа;
- Тела запроса/ответа.
И клиент, и сервер могут посылать друг другу заголовки и тело ответа. У клиента доступные заголовки будут одни, у сервера — другие. Рассмотрим, как выглядит работа по протоколу HTTP, когда пользователь хочет загрузить главную страницу социальной сети «ВКонтакте».
1 Браузер пользователя устанавливает соединение с сервером vk и отправляет следующий запрос:
GET / HTTP/1.1
Host: vk.com
2 Сервер принимает запрос и отправляет ответ:
HTTP/1.1 200 OK
Server: Apache
<html>
<head>
<title>ВКонтакте</title>
</head>
<!-- остальной контент страницы ниже -->
3 Браузер принимает ответ и показывает готовую страницу.
Работа с заголовками в php
В PHP есть все возможности для взаимодействия с HTTP:
- Получение заголовков запроса;
- Получение тела запроса;
- Добавление/изменение заголовков ответа;
- Управление телом ответа.
Получение заголовков запроса
Напомним ещё раз, что заголовки запроса — это метаинформация, отправленная браузером при запросе сценария.
PHP автоматически извлекает такие заголовки и помещает их в специальный массив — $_SERVER
. Стоит отметить, что в этом массиве, помимо заголовков, есть и другая информация. Значения заголовков запроса находятся под ключами, которые начинаются с HTTP_
. Подробно всё содержимое этого массива описано в официальной документации.
Пример, как получить предыдущую страницу, с которой перешёл пользователь:
print($_SERVER['HTTP_REFERER']);
Получение тела запроса
Тело запроса — это информация, которую передал браузер при запросе страницы. Но тело запроса присутствует только, если браузер запросил страницу методом POST
. Дело в том, что POST
— это метод, специально предназначенный для отправки данных на сайт. Чаще всего метод POST
браузер задействует в момент отправки формы. В этом случае телом запроса будет содержимое формы.
В PHP-сценарии все данные отправленной формы будут доступны в специальном массиве $_POST
. Более подробно об этом написано в следующей главе, посвящённой формам.
Добавление/изменение заголовков ответа
В PHP-сценарии можно управлять всеми заголовками ответа, которые попадут к пользователю вместе с контентом страницы. Это возможно, потому что PHP работает на стороне веб-сервера и имеет с ним очень тесную интеграцию. Вот примеры сценариев, когда пригодится управление заголовками ответа:
- Кэширование;
- Переадресация пользователя;
- Установка cookies;
- Отправка файлов;
- Передача дополнительной информации браузеру.
Заголовки ответа нужны для выполнения множества важных задач.
В PHP есть функция для отправки или смены заголовков: header()
.
Она принимает имя и значение заголовка и добавляет его в список из всех заголовков, которые уйдут в браузер пользователя после окончания работы сценария.
За переадресацию отвечает заголовок с именем Location
, а через двоеточие задаётся значение — адрес страницы для перехода:
header("Location: /index.php");
Управление телом ответа
Всё, что PHP выводит на экран, является содержимым ответа. Иными словами, вызовы функций print
, echo
являются телом ответа, которое попадает в браузер пользователю.
Важное замечание по использованию заголовков
Есть одно ограничение: заголовки нельзя отправлять, если пользователю к этому моменту уже отправили любой контент. То есть если показать что-то на экране, например, через функцию print()
, то после этого заголовки поменять уже не получится.
Параметры запроса
Мы привыкли, что на нашем сайте каждый PHP-сценарий отвечает за одну страницу. Посетитель сайта вводит в адресную строку путь, который состоит из имени домена и имени PHP-сценария. Например, так: http://weather-diary.ru/day.php
.
Но как быть, если одна страница должна показывать разную информацию?
На сайте дневника наблюдений за погодой мы сделали отдельную страницу, чтобы показывать на ней информацию о погоде из истории за один конкретный день. То есть страница одна, но показывает разные данные, в зависимости от выбранного дня.
Также пользователи хотят добавить в закладки адреса страниц с нужными им днями. Получается, что, имея только один сценарий, сделать страницу, способную показывать дневник погоды за любой день невозможно? Вовсе нет!
Из чего состоит URI
URI — это уникальный идентификатор ресурса. Ресурс в нашем случае — это полный путь до страницы сайта. И вот как может выглядеть ресурс для показа погоды за конкретный день:
http://weather-diary.ru/day.php?date=2017-10-15
Разберём, из чего состоит этот URI.
Здесь есть имя домена: weather-diary.ru
.
Затем идёт имя сценария: day.php
.
А всё, что идёт после — это параметры запроса.
Параметры запроса — это как бы дополнительные атрибуты адреса страницы. Они отделяются от имени страницы знаком запроса. В примере выше параметр запроса только один: date=2017-10-30.
Имя этого параметра: date
, значение: 2017-10-15
.
Параметров запроса может быть несколько, тогда они разделяются знаком амперсанда: ?date=2017-10-15&tscale=celsius
.
В примере выше указывается два аргумента: дата и единица измерения температуры.
Параметры запроса — как внешние переменные
Теперь в адресе страницы используются параметры запроса, но какая нам от этого польза? Она состоит в том, что если имя страницы вызывает к исполнению соответствующий PHP-сценарий, то параметры запроса превращаются в специальные внешние переменные в этом сценарии. То есть если в адресе присутствуют такие параметры, то их легко получить внутри кода сценария и выполнить с ними какие-нибудь действия. Например, показать погоду за конкретный день в выбранных единицах измерения.