Сессии
| Автор: | Артемьев Сергей Игоревич |
| ICQ: | 438856621 |
| email: | _spin_@bk.ru |
Одной из особенностей протокола HTTP является "отсутствие памяти". Это означает, что сервер "забывает" пользователя сразу же после окончания HTTP-сессии (загрузки страницы). Даже если просто обновить ранее загруженную страницу - сервер будет считать, что к нему обратился новый пользователь.
Для статического сайта это вполне достаточно, т.к. содержимое страниц не меняется и всем пользователям показывается одно и то же.А вот для динамических сайтов дело обстоит намного хуже - здесь сервер должен каким-то образом отличать пользователей друг от друга и выдавать каждому из них нужные данные.
PHP предлагает решение на основе сессий. Сессия - это набор параметров и значений, однозначно определяющих пользователя. Каждая сессия обладает собственным уникальным идентификатором, поэтому пользователю достаточно сообщить серверу идентификатор своей сессии и сервер "вспомнит" все подробности и историю запросов пользователя.
Идентификатор сессии автомаически сохраняется в браузере пользователя в виде cookie, а если браузер cookie не поддерживает - идентификатор добавляется автоматически к адресу страницы и всем ссылкам на ней. Это значит, что при обновлении страницы браузер сам отправит на сервер идентификатор сессии, независимо от действий пользователя.
В зависимости от настроек PHP сессии могут создаваться либо вручную, либо автоматически при первом обращении пользователя. У большинство провайдеров автоматическое создание сессий не включено из соображений производительности и безопасности.
Для создания новой сессии необходимо вызвать функцию session_start() без параметров, после этого станет доступен глобальный массив $_SESSION и в cookies браузера пользователя появится элемент PHPSESSID.
<?php
session_start();
$_SESSION['sampleName'] = 'Иван Иваныч';
echo $_SESSION['sampleName'];
?>
Сессия инициируется один раз, а все повторные вызовы session_start() приводят только к появлению предупреждения "Сессия уже открыта, повторное открытие не допускается.". Для проверки, была ли уже вызвана функция session_start() существует специальная функция session_id(). Эта функция всегда возвращает строку с идентификатором сессии, но если сессия ещё не создана - строка будет пустой.
<?php
// открываем сессию только если она ещё
// не была открыта ранее
if(session_id() == '')
session_start();
?>
Этот приём очень удобен, когда ваш скрипт подключает другие скрипты, в которых так же может быть вызвана session_start().
Для того, чтобы ваши данные сохранялись на сервере при переходах между страницами, достаточно поместить их в глобальный массив $_SESSION. Например:
<?php
// открываем сессию
session_start();
// проверяем на наличие имени в URL-запросе
if(isset($_GET['name']))
{
// получаем имя
$name = $_GET['name'];
// и сохраняем его в сессии
$_SESSION['name'] = $name;
echo 'Имя извлечено из GET-запроса' .
"<br />\n";
}
// иначе - проверяем наличие имени в сессии
elseif(isset($_SESSION['name']))
{
// извлекаем имя из сессии
$name = $_SESSION['name'];
echo 'Имя извлечено из данных сессии' .
"<br />\n";
}
// иначе - выводим сообщение об ошибке.
else
{
$name = 'не обнаружено';
echo 'Имя не обнаружено' .
"<br />\n";
}
// выводим имя
echo 'Моё имя: ' . $name;
?>
Сохраните этот код в файле myname.php в корневом каталоге локального сервера и перейдите по адресу http://localhost/myname.php. Скрипт выведет сообщение, что имя не обнаружено.
Теперь измените адрес страницы, дописав к нему "?name=Ivan" и перейдите по новому адресу. Скрипт сообщит, что обнаружил имя в GET-запросе, и что ваше имя -Ivan. А теперь снова перейдите по первому адресу (без параметров). Скрипт сообщает, что имя извлечено из данных сессии, и что ваше имя по прежднему Ivan,
Иногда возникают ситуаци, когда надо заново сгенерировать идентификатор сессии. Для этого служит функция session_regenerate_id(). Вызывать её нужно после открытия сессии:
<?php
if(session_id() == '')
session_start();
else session_regenerate_id();
?>
Показаный приём иногда используется при защите сайтов от атак, заключающихся в подмене злоумышленником своего идентификатора сессии на идентификатор пользователя с более высокими привилегиями. Подобрать чужой идентификатор практически невозможно, а вот узнать (прослушивая сеть сниффером или пользуясь троянами) - возможно.
Элементы сессии могут быть не только простых типов, но и массивами:
<?php
...
$_SESSION['myWorkWeek'] = array();
...
$_SESSION['myWorkWeek']['monday'] = 'Понедельник';
$_SESSION['myWorkWeek']['tuesday'] = 'Вторник';
...
$_SESSION['myWorkWeek']['friday'] = 'Пятница';
echo 'Мои рабочие дни: ' .
implode(', ', $_SESSION['myWorkWeek']);
// выведет:
// Мои рабочие дни: Понедельник, Вторник, ...
?>
Сессию можно закрыть или уничтожить. Закрытие сессии происходит при вызове функции session_write_close(). При этом все изменения, сделанные в сессии, сохраняются в дисковом кеше. Если же необходимо закрыть сессию и удалить все её данные - надо вызвать session_destroy() или session_unset(). Отличие между ними в том, что session_unset() может использоваться в старом коде, где недоступен глобальный массив $_SESSION.
<?php
...
// освобождаем все переменные сессии
$_SESSION = array();
// стираем cookie идентификатора сессии
if (isset($_COOKIE[session_name()]))
{
setcookie(session_name(), '', time()-42000, '/');
}
// уничтожаем сессию
session_destroy();
?>
Как видите, работать с сессиями достаточно просто. Только не надо забывать, что объём данных, сохраняемых в сессии, в конце концов конечен и не надо сохранять лишнего.