Механизм работы сессий

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

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

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

 

Инициализация сессии и регистрация переменных

session_start
Эта функция инициализирует механизм сессий для текущего пользователя, запустившего сценарий.

Синтаксис:
void session_start()

· Если посетитель запускает программу впервые, у него устанавливается Cookies с уникальным идентификатором, и создается временное хранилище, ассоциированное с этим идентификатором.

· Определяется, какое хранилище связано с текущим идентификатором пользователя.

· Если в хранилище имеются какие-то переменные, их значения восстанавливаются. Точнее, создаются глобальные переменные, которые были сохранены в сессии при предыдущем завершении сценария.

Надо заметить, что если вы поставили в настройках PHP режим session.auto_start=1, то функция инициализации вызывается автоматически при запуске сценария. Так же надо следить за тем, чтобы до нашей функции не было никакого вывода в браузер - иначе PHP не сможет установить SID для пользователя.
Функция всегда возвращает true.

session_register
Указывает PHP на то, что ту или иную переменную нужно сохранить в сессии.

Синтаксис:
bool session_register(mixed name [, mixed name1,...])

Функция принимает в параметрах одно или несколько имен переменных (имена задаются в скобках, без знака $ слева), регистрируют их в текущей запущенной сессии и возвращает true, если регистрация прошла успешно.

Повторная запись одной переменной в сессии не приведет к ошибке.

<?session_start();session_register("count");$count=@$count+1;?><h2>Счетчик</h2>В текущей сессии работы с браузером вы открыли эту страницу<?=$count?> раз(а). Закройте браузер, чтобы обнулить счетчик.</body>

 






Имя группы сессии

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

Пусть разработчик А написал сценарий счетчика. Он использует переменную $count, и не имеет никаких проблем. До тех пор, пока разработчик В, ничего не знающий о сценарии А, не создал систему статистики, которая тоже использует сессии. Самое ужасное, что он также регистрирует переменную $count, не зная о том, что она уже занята. В результате, как всегда, страдает пользователь: запустив сначало сценарий разработчика В, а потом - А, он видит, что данные счетчиков перемешались.

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

session_name
Эта функция устанавливает или возвращает имя группы сессии, которая будет использоваться PHP для хранения зарегестрированных переменных.

Синтаксис:
string session_name([string $newname])

Если $newname не задан, то возвращается текущее имя. Если же этот параметр указан, то имя группы будет изменено на $newname, при этом функция вернет предыдущее имя.

Отметим, что session_name() лишь сменяет имя текущей группы и сессии, но не создает новую сессию и временное хранилище. Это значит, что мы должны в большинстве случаев вызывать session_name(имя_группы) еще до ее инициализации - вызова session_start(), в противном случае мы получим совсем не то, что ожидали.

Если функция session_name() не была вызвана по инициализации, PHP будет использовать имя по умолчанию - PHPSESID.
Пример:

<?session_name("CounterScript"session_start();session_register("count");$count=@$count+1;?>В текущей сессии вы открыли эту страницу <?=$count?> раз(а).

 





Идентификатор сессии

Итак, идентификатор сессии является именем временного хранилища, которое будет использовано для хранения данных сессии между запусками сценария. Один SID - одно хранилище. Нет SID, нет и хранилища, и наоботот.
так как же соотностится идентификатор и имя группы? Имя - это всего лишь собирательное название для нескольких сессий (то есть, для многих SID), запущенных разными пользователями. Один и тот же клиент никогда не будет иметь два различных SID в пределах одного имени группы. Но его браузер вполне может работать с несколькими SID, расположенными логически в разных "пространствах имен".

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

session_id
Эта функция возвращает текущий идентификатор сессии SID.

Синтаксис:
string session_id([string $sid])

Если задан параметр $sid, то у активной сессии изменяется идентификатор на $sid.
Вызвав session_id() до session_start(), мы можем подключиться к любой (в том числе и к чужой) сессии на сервере, если знаем ее идентификатор. Мы можем также создать сессию с угодным нам идентификатором, при этом автоматически установив его в Cookies пользователя.

 





Идентификатор сессии

Итак, идентификатор сессии является именем временного хранилища, которое будет использовано для хранения данных сессии между запусками сценария. Один SID - одно хранилище. Нет SID, нет и хранилища, и наоботот.
так как же соотностится идентификатор и имя группы? Имя - это всего лишь собирательное название для нескольких сессий (то есть, для многих SID), запущенных разными пользователями. Один и тот же клиент никогда не будет иметь два различных SID в пределах одного имени группы. Но его браузер вполне может работать с несколькими SID, расположенными логически в разных "пространствах имен".

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

session_id
Эта функция возвращает текущий идентификатор сессии SID.

Синтаксис:
string session_id([string $sid])

Если задан параметр $sid, то у активной сессии изменяется идентификатор на $sid.
Вызвав session_id() до session_start(), мы можем подключиться к любой (в том числе и к чужой) сессии на сервере, если знаем ее идентификатор. Мы можем также создать сессию с угодным нам идентификатором, при этом автоматически установив его в Cookies пользователя.

 





Обзор обработчиков

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

Синтаксис:
bool handler_open(string $save_path, string $session_name)

Функция вызывается, когда вызывается session_start(). Обработчик должен взять на себя всю работу, связанную с открытием базы данных для группы сессий с именем $session_name. В параметре $save_path передается то, что было указано при вызове session_save_path() или же путь к файлам-хранилищам данных сессий по умолчанию.

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

Синтаксис:
bool handler_close()

handler_read
Чтение данных сессии.

Синтаксис:
string handler_read(string $sid)

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

имя1=значение1;имя2=значение2;имя3=значение3;...

имяN задает имя очередной переменной, зарегестрированной в сессии, а занчениеN - результат вызова функции Serialize() для значения этой переменной.
Например, наша запись может иметь следующий вид:

foo|i:1;count|i:10;

Она говорит о том, что из временного хранилища были прочитаны две целые переменные, первая из которых равна 1, а вторая - 10.

handler_write
Запись данных сессии.

Синтаксис:
string handler_write(string $sid, string $data)

Этот обработчик предназначен для записи данных сессии с идентификатором $sid во временное хранилище - например, открытое ранее обработчиком handler_open(). Параметр $data задается в точно таком же формате. Фактически, чаще всего действие этой функции сводится к записи в базу данных строки $data без каких-либо ее изменений.

handler_gc
Очищает временное хранилище данных через определенный промежуток времени.

Синтаксис:
bool handler_gc(int $maxlifetime)

Этот обработчик вызывается каждый раз при завершении работы сценария. Если пользователь окончательно покинул сервер, заначит, данные сессии во временном хранилище можно уничтожить. Этим и должна заниматься функция handler_gc(). Ей передается в параметрах то время (в секундах), по прошествии которого PHP принимает решение о необходимости удалить все ненужные данные.

session_set_save_handler
Регистрация обработчиков.

При описании обработчиков мы указывали их имена с префиксом handler. На самом деле, это совсем не является обязательным. Даже наоборот - вы можете давать такие имена своим обработчикам, какие только захотите.

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

Синтаксис:
void session_set_save_handler($open, $close, $read, $write, $destroy, $gc)

Эта функция регестрирует подпрограммы, имена которых переданы в ее параметрах, как обработчики текущих сессии. Параметр $open содержит имя функции, которая будет вызвана при инициализации сессии, а $close - функции, вызываемой при ее закрытии. В $read и $write нужно указать имена обработчиков, соответственно, для чтения и записи во временное хранилище. Функция с именем, заданным в $destroy, будет вызвана при уничтожении сессии. Наконец, обработчик, определяемый параметром $gc, используется как обработчик мусора.

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

 















Про сессии и Cookies

Проблема: - отключены Cookies
Бытует распространенное мнение, что сессии без Cookies не может существовать. Действительно, Cookies наиболее просто решает проблему идентификации пользователя, что необходимо для связи временного хранилища и данных сессии. Но вот что делать, если пользователь у себя в настройках отключил прием Cookies?
На этот случай разработчики PHP позаботились о передаче идентификаторов сессии не в Cookies, а каким-нибудь аналогичным путем, например через адресную строку броузера.
Решение: - изменение гиперссылок и форм
В PHP существует одна специальная константа с именем SID. Она всегда содержит имя группы сессии и ее идентификатор в формате имя=идентификатор. Именно в таком формате данные принимаются, когда они приходят из Cookies браузера. Таким образом, нам достаточно просто передать значение константы SID в сценарий, чтобы он "подумал", будто бы данные пришли из Cookies.
Вот пример использования сессий без Cookies:

<?session_name("testses");session_start();session_register("i");$i=@$i+1;?><body>Вы открыли эту страницу<?=$i?> раз. При закрытии браузера счетчик обнулиться.<BR><A href=sesclick.php?<?=SID?>>Нажмите для записи в счетчик!</A></body>

Этот пример будет работать, если у пользователя действительно отключены Cookies. Если они включены, PHP просто не будет генерировать константу SID и задействует Cookies.

Но в приведенном способе есть одно неудобство, а именно, везде в участки кода нужно вставлять <?=SID?>, и если вы гдето пропустили, то программа может не работать!
К счастью, разработчики PHP учли эту возможность, и решили уберечь нас от этого. По-этому если в какой-нибудь гиперссылке вы по ошибке пропустите <?=SID?>, PHP вставит его автоматически. При этом не повредив остальные параметры, которые могут присутствовать в URL.

Для проверки можно использовать следующий пример:

<?session_start()?><body><A href="php.php">PHP</A><A href="php.php?ss=1">PHP - выражения</A>

Вот что получиться, при наведении мышки на эти ссылки:

http://www.spravkaweb.ru/php.php?PHPSESSID=81456f6a886f2104
http://www.spravkaweb.ru/php.php?ss=1&PHPSESSID=34f5d04a35601510f45

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

<?session_start()?><form action=act.php mathod=post></form>

А вот что получиться при просмотре нашей страницы в виде HTML:

<form action="act.php" method="post"><INPUT TYPE=HIDDEN NAME="PHPSESSID" VALUE="0a561093f84d4321"></form>

Из примера мы видим, что PHP добавил в форму скрытое поле с нужным именем и занчением.

 










Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: