PHP 4 на практике




Отслеживание сеанса


Сеансом (session) называется период времени, который начинается с момента прихода пользователя на сайт и завершается, когда пользователь покидает сайт. В течение сеанса часто возникает необходимость в сохранении различных переменных, которые бы «сопровождали» пользователя при перемещениях на сайте, чтобы вам не приходилось вручную кодировать многочисленные скрытые поля или переменные, присоединяемые к URL.

Рассмотрим следующую ситуацию. При входе на сайт пользователю присваивается уникальный идентификатор сеанса (SID), который сохраняется на компьютере пользователя в cookie с именем PHPSESSJD. Если использование cookie запрещено или cookie вообще не поддерживаются, SID автоматически присоединяется ко всем локальным URL на протяжении сеанса. В то же время на сервере сохраняется файл, имя которого совпадает с SID. По мере того как пользователь перемещается по сайту, значения некоторых параметров должны сохраняться в виде сеансовых переменных. Эти переменные сохраняются в файле пользователя. При последующем обращении к сеансовой переменной сервер открывает сеансовый файл пользователя и ищет в нем нужную переменную. В сущности, в этом и заключается суть отслеживания сеанса. Конечно, информация с таким же успехом может храниться в базе данных или в другом файле.

Интересно? Еще бы. После всего сказанного вы, несомненно, лучше поймете различные проблемы конфигурации, рассматриваемые ниже. Особенно важную роль играют три флага. Первый флаг, --enable-trans-id, включается в процесс конфигурации в том случае, если вы собираетесь использовать SID (см. ниже). Два других флага, track_vars и register_globals, включаются и отключаются по мере необходимости в файле php.ini. Последствия активизации этих флагов рассматриваются ниже.

--enable-trans-id

Если РНР компилируется с этим флагом, ко всем относительным URL автоматически присоединяется идентификатор сеанса (SID). Дополнение записывается в формате имя_сеанса=идентификатор_сеанса, где имя_сеанса определяется в файле php.ini (см. ниже). Если вы не захотите включать этот флаг, в качестве SID можно использовать константу.

track_vars

Установка флага track_vars позволяет использовать массивы $HTTP_*_VARS[], где * заменяется одним из значений EGPCS (Environment, Get, Post, Cookie, Server). Данный флаг необходим для того, чтобы значения SID передавались с одной страницы на другую. В РНР 4.03 этот флаг всегда находится в установленном состоянии.

register_globals

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

Если флаг register_globals сброшен, а флаг track_vars установлен, ко всем переменным GPC можно обращаться через массив $HTTP_*_VARS[]. Например, если сбросить флаг register_globals, к стандартной переменной $PHP_SELF придется обращаться в виде $HTTP_SERVER_VARS["PHP_SELF"].

Существует целый ряд других аспектов конфигурации, о которых следует позаботиться. Эти директивы перечислены в табл. 13.1 с указанием стандартных значений, задаваемых по умолчанию в файле php.ini. Перечисление производится в порядке появления директив в файле.

Таблица 13.1. Сеансовые директивы в файле php.ini

Директива Описание
session.save_handler = files

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

session.save_path =/tmp

Определяет каталог для сеансовых файлов РНР. На платформе Linux обычно используется значение по умолчанию ('/tmp'). На платформе Windows следует указать путь к какому-нибудь каталогу, в противном случае произойдет ошибка

session_use_cookies =1

При установке этого флага для сохранения идентификатора сеанса на компьютере пользователя используются cookie

session.name =PHPRESSID.

Если флаг session.use_cookies установлен, то значение session.name используется в качестве имени cookie. Имя может состоять только из алфавитно-цифровых символов

session.auto_start = 0

При установке флага session.auto_start сеанс автоматически инициируется при первоначальном запросе со стороны клиента

 session.cookie_lifetime = 0

Если флаг session.use_cookies установлен, то значение session.cookie_lifetime определяет срок действия отправляемых cookie. Если параметр равен 0, то все cookie становятся недействительными при завершении сеанса

session.cookie_path = /

Если флаг session.use_cookies установлен, то значение session.cookie_path определяет каталог, для которого отправляемые cookie считаются действительными

 session.cookie_domain =

Если флаг session.use_cookies установлен, то значение session.cookie_domain определяет домен, для которого отправляемые cookie считаются действительными

session.serialize_handler = php

Имя обработчика, используемого в процессе сериализации данных. В настоящее время определены два возможных значения: php и WDDX

session.gc_probability =1 Вероятность активизации сборщика мусора РНР (в процентах)
session.gc_maxlifetime=1440

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

session.referer_check = 

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

session.enthropy_fiie =

Ссылка на внешний файл с дополнительной случайной информацией, используемой при генерации идентификаторов сеансов. В системах UNIX для этой цели обычно используются два устройства, /dev/random и /dev/urandom. Устройство /dev/random получает случайные данные от ядра, а устройство /dev/urandom генерирует случайную строку при помощи хэш-алгоритма М05. Короче говоря, /dev/random работает быстрее, a /dev/urandom генерирует «более случайные» строки

session.enthropy_length = 0 Если флаг session.enthropy_file установлен, то session.enthropyjength определяет количество байт, читаемых из файла session.enthropy_file
session.cache limiter = nocache Способ управления кэшем для страниц сеанса. В настоящее время определены три возможных значения: nocache, public и private
session.cache_expire =180 Продолжительность жизни кэшированных страниц сеанса (в минутах)

После внесения всех необходимых изменений в настройку сервера мы переходим к непосредственной реализации отслеживания сеанса на вашем сайте. Благодаря нескольким стандартным функциям РНР этот процесс не так уж сложен. Первое, что необходимо знать, — сеанс инициируется функцией session_start( ). Конечно, при включении директивы session.auto_start в файл php.ini (см. выше) необходимость в вызове этой функции отпадает. Тем не менее, в оставшейся части этого раздела я буду использовать эту функцию, чтобы примеры выглядели более последовательно. Функция session_start( ) имеет простой синтаксис, поскольку она не получает параметров и возвращает логическую величину.

Отслеживание
сеансаДиректива session.save_handler настолько важна, что я счел необходимым посвятить ей отдельный раздел. Он находится в конце главы под заголовком «Назначение пользовательских функций для хранения сеансовых данных».

session_start( )

Функция session_start( ) имеет двойное назначение. Сначала она проверяет, начал ли пользователь новый сеанс, и если нет — начинает его. Синтаксис функции

session_start( ): boolean session_start()

Если функция начинает новый сеанс, она выполняет три операции: назначение пользователю SID, отправку cookie (если в файле php.ini установлен флаг session_cookies) и создание файла сеанса на сервере. Второе назначение функции заключается в том, что она информирует ядро РНР о возможности использования в сценарии, в котором она была вызвана, сеансовых переменных.

Сеанс начинается простым вызовом session_start( ) следующего вида:

session_start( ):

Если сеанс можно создать, значит, его можно и уничтожить. Это делается функцией session_destroy( ).

Отслеживание
сеансаФункция session_start( ) возвращает TRUE независимо от результата. Следовательно, проверять ее в условиях if или в команде die( ) бессмысленно.

session_destroy()

Функция session_destroy( ) уничтожает все хранимые данные, относящиеся к сеансу текущего пользователя. Синтаксис функции session_destroy( ):

boolean session_destroy( )

Следует помнить, что эта функция не уничтожает cookie на браузере пользователя. Впрочем, если вы не собираетесь использовать cookie после конца сеанса, просто присвойте параметру session.cookie_lifetime в файле php.ini значение ( ) (используемое по умолчанию). Пример использования функции:

<?

session_start( );

// Выполнить некоторые действия для текущего сеанса

session_destroy( ):

?>

Теперь вы умеете уничтожать сеансы, и мы можем перейти к работе с сеансовыми переменными. Возможно, самой важной сеансовой переменной является SID (идентификатор сеанса). Его легко можно получить при помощи функции session_id( ).

session_id( )

Функция session_id( ) возвращает SID для сеанса, созданного функцией session_start( ). Синтаксис функции session_id( ):

string session_id ([string sfd])

Если в необязательном параметре передается идентификатор, то значение SID текущего сеанса изменяется. Однако следует учитывать, что cookie при этом заново не пересылаются. Пример:

<?

session_start()

print "Your session identification number is ".sessionjd( ):

session_destroy( ):

?>

Результат, выводимый в браузере, выглядит примерно так:

Your session identification number is 067d992a949114ee9832flcllcafc640

Как же создать свою сеансовую переменную? С помощью функции session_register( ).

session_register( )

Функция session_register( ) регистрирует имена одной или нескольких переменных для текущего сеанса. Синтаксис функции session_register( ):

boolean session_register (mixed имя_переменной1 [, mixed имя_переменной2... ])

Следует помнить, что вы регистрируете не сами переменные, а их имена. Если сеанс не существует, функция session_register( ) также неявно вызывает session_start( ) для создания нового сеанса.

Прежде чем приводить примеры использования session_register( ), я хочу представить еще одну функцию, связанную с отслеживанием сеанса, — session_is_registered( ). Эта функция проверяет, была ли зарегистрирована переменная с заданным именем.

session_is_registered( )

Часто требуется определить, была ли ранее зарегистрирована переменная с заданным именем. Задача решается при помощи функции session_is_registered( ), имеющей следующий синтаксис:

boolean session_is_registered (string имя_переменной)

Применение функций session_register( ) и session_is_registered( ) будет продемонстрировано на классическом примере использования сеансовых переменных — счетчике посещений (листинг 13.5).

Листинг 13.5. Счетчик посещений сайта пользователем

<?

session_start( ):

if (! sessionjs_registered('hits')) :

session_register( 'hits' ) ;

endif ;

$hits++:

print "You've seen this page $hits times.

?>

Сеансовые переменные можно не только создавать, но и уничтожать. Для этой цели применяется функция session_unregister( ).

session_unregister( )

Сеансовые переменные уничтожаются функцией session_unregister( ). Синтаксис:

boolean session_unregister (string имя_переменной')

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

<?

session_start()

session_register('username');

// Использовать переменную $username.

// Когда переменная становится ненужной - уничтожить ее.

session_unregister('username');

session_destroy();

?>

Как и в случае с функцией session_register, помните, что в параметре указывается не сама переменная (то есть имя с префиксом $). Вместо этого указывается имя переменной.

session_encode( )

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

boolean session_encode( )

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

Пример использования session_encode( ) приведен в листинге 13.6. Предположим, что на компьютере «зарегистрированного» пользователя имеется cookie, в котором хранится уникальный идентификатор этого пользователя. Когда пользователь запрашивает страницу, содержащую листинг 13.6, UID читается из cookie и присваивается идентификатору сеанса. Мы создаем несколько сеансовых переменных и присваиваем им значения, после чего форматируем всю информацию функцией session_encode( ) и заносим в базу данных MySQL.

Листинг 13.6. Использование функции session_encode( ) для сохранения данных в базе данных MySQL

<?

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

session_register('bgcolor');

session_register('fontcolor');

// Предполагается, что переменная $usr_id (с уникальным

// идентификатором пользователя) хранится в cookie

// на компьютере пользователя.

// При помощи функции session_id( ) присвоить идентификатору

// сеанса уникальный идентификатор пользователя (UID),

// хранящийся в cookie. $id = session_id($usr_id);

// Значения следующих переменных могут задаваться пользователем

// на форме HTML $bgcolor = "white"; $fontcolor = "blue";

// Преобразовать все сеансовые данные в одну строку

$usr_data = session_encode( );

// Подключиться к серверу MySQL и выбрать базу данных users

@mysql_pconnect("localhost", "web", "4tf9zzzf")

or die("Could not connect to MySQL server!");

@mysql_select_db("users")

or die("Could not select user database!");

// Обновить пользовательские параметры страницы

$query = "UPDATE user_info set page_data='$usr_data' WHERE user_id= '$id'";

$result - mysql_query($query) or die("Could not update user information!");

?>

Как видите, быстрое преобразование всех сеансовых переменных в одну строку избавляет нас от необходимости создавать несколько полей для хранения/загрузки данных, а также несколько уменьшает объем программы.

session_decode( )

Все сеансовые данные, ранее преобразованные в строку функцией sessi on_encode( ), восстанавливаются функцией session_decode( ). Синтаксис:

string session_decode (string сеансовые_данные)

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

В листинге 13.7 продемонстрировано восстановление закодированных сеансовых переменных функцией session_decode( ). Предположим, таблица MySQL с именем user_info состоит из двух полей: user_id и page_data. Пользовательский UID, хранящийся в cookie на компьютере пользователя, применяется для загрузки сеансовых данных, хранящихся в поле page_data. В этом поле хранится закодированная строка переменных, одна из которых ($bgcolor) содержит цвет фона, выбранный пользователем.

Листинг 13.7. Восстановление сеансовых данных, хранящихся в базе данных MySQL

<?

// Предполагается, что переменная $usr_id (с уникальным

// идентификатором пользователя) хранится в cookie

// на компьютере пользователя.

$id = session_id($usr_id);

// Подключиться к серверу MySQL и выбрать базу данных users

@mysq]_pconnect("localhost", "web", "4tf9zzzf")

or die("Could not connect to MySQL server!");

@mysql_select_db("users")

or die("Could not select company database!");

// Выбрать данные из таблицы MySQL

$query = "SELECT page_data FROM user_info WHERE user_id= '$id'",

Sresult = mysql_query($query);

$user_data = mysql_result($result, 0. "page_data");

// Восстановить данные session_decode($user_data):

// Вывести одну из восстановленных сеансовых переменных

print "BGCOLOR: $bgcolor";

?>

Как видно из двух приведенных листингов, функции session_ encode( ) и ses-sion_decode( ) обеспечивают очень удобные и эффективные сохранение и загрузку сеансовых данных.









Начало    Назад    Вперед