| |
ли
мы храним данные сессии в базе данных, мы просто должны удалить из нее все
запи-
си, доступ к которым не осуществлялся более, чем $maxlifetime секунд. Таким об-
разом, "застарелые" временные хранилища будут иногда очищаться.
На самом деле обработчик handler_gc() вызывается не при каждом запуске
сценария, а только изредка. Когда именно — определяется конфигурационным
параметром session.gc_probability. А именно, им задается (в процен-
тах), какова вероятность того, что при очередном запуске сценария будет вы-
бран обработчик "чистки мусора". Сделано это для улучшения производитель-
ности сервера, потому что обычно сборка мусора — довольно ресурсоемкая
задача, особенно если сессий много.
Регистрация обработчиков
Вы, наверное, обратили внимание, что при описании обработчиков я указывал их
имена с префиксом handler. На самом деле, это совсем не является обязательным.
Даже наоборот — вы можете давать такие имена своим обработчикам, какие только
захотите.
Но возникает вопрос: как же тогда PHP их найдет? Вот для этого и существует
функ-
ция регистрации обработчиков, которая говорит интерпретатору, какую функцию он
должен вызывать при наступлении того или иного события.
void session_set_save_handler($open,$close,$read,$write,$destroy,$gc)
Эта функция регистрирует подпрограммы, имена которых переданы в ее параметрах,
как обработчики текущей сессии. Параметр $open содержит имя функции, которая
будет вызвана при инициализации сессии, а $close — функции, вызываемой при ее
закрытии. В $read и $write нужно указать имена обработчиков, соответственно,
для чтения и записи во временное хранилище. Функция с именем, заданным в
Часть IV. Стандартные функции PHP 354
$destroy, будет вызвана при уничтожении сессии. Наконец, обработчик, определяе-
мый параметром $gc, используется как сборщик мусора.
Эту функцию можно вызывать только до инициализации сессии, в противном случае
она просто игнорируется.
Пример: переопределение обработчиков
Давайте напишем пример, который бы иллюстрировал механизм переопределения
обработчиков. Мы будем держать временные хранилища сессий в подкаталоге
sessiondata текущего каталога, и для каждого имени группы сессий создавать от-
дельный каталог.
Код листинга 25.2 довольно велик, но не сложен. Тут уж ничего не поделаешь —
нам
в любом случае приходится задавать все 6 обработчиков, а это выливается в
"объе-
мистые" описания.
Листинг 25.2. Переопределение обработчиков сессии
// Возвращает полное имя файла временного хранилища сессии.
// В случае, если нужно изменить тот каталог, в котором должны
// храниться сессии, достаточно поменять только эту функцию
function ses_fname($key)
{
return "sessiondata/".session_name()."/$key";
}
// Заглушки — эти функции просто ничего не делают
function ses_open($save_path, $ses_name) { return true; }
function ses_close() { return true; }
// Чтение данных из временного хранилища
function ses_read($key)
{
// Получаем имя файла и открываем файл
$fname=ses_fname($key);
$f=@fopen($fname,"rb"); if(!$f) return "";
// Читаем до конца файла
$st=fread($f,filesize($fname));
fclose($f);
return $st;
}
Глава 25. Управление сессиями 355
// Запись данных сессии во временное хранилище
function ses_write($key, $val)
{
$fname=ses_fname($key);
// Сначала создаем все каталоги (в случае, если они уже есть,
// игнорируем сообщения об ошибке)
@mkdir($d=dirname(dirname($fname)),0777);
@mkdir(dirname($fname),0777);
// Создаем файл и записываем в него данные сессии
$f=@fopen($fname,"wb"); if(!$f) return "";
fwrite($f,$val);
fclose($f);
return true;
}
// Вызывается при уничтожении сессии
function ses_destroy ($key)
{
return @unlink(ses_fname($key));
}
// Сборка мусора — ищем все старые файлы и удаляем их
function ses_gc($maxlifetime)
{
$dir=ses_fname(".");
// Получаем доступ к каталогу текущей группы сессии
$d=@opendir($dir); if(!$d) return false;
$DelDir=1; // Признак того, что каталог пуст, и его можно удалить
// Читаем все элементы каталога
while(($e=readdir($d))!==false) {
// Если это "точки", пропускаем их
if($e=="."||$e=="..") continue;
// Файл слишком старый?
if(time()-filemtime($fname="$dir/$e")>=$maxlifetime) {
@unlink($fname);
continue;
}
// Нашли не очень старый файл — значит, каталог точно
Часть IV. Стандартные функции PHP 356
// не будет в результате работы пуст.
$DelDir=0;
}
closedir($d);
// Если все файлы оказались слишком старые и удалены,
// удалить и каталог
if($DelDir) @rmdir($dir);
return true;
}
// Регистрируем наши новые обработчики
session_set_save_handler(
"ses_
|
|