PHP сессия в базе данных

версия для печати

Хочу организовать хранение сессий на стороне сервера в базе данных. Зачем? "Just for fun!" ©. Вы можете найти для себя другие причины :)

Оказалось, свой велосипед не нужен, в PHP уже все есть. Нужно реализовать интерфейс php::SessionHandlerInterface и где-то назначить сессионным обработчиком объект моего класса. Для этого вызываем функцию php::session_set_save_handler(). Проще всего сделать вызов в bootstrap.php или index.php приложения.

Очень полезно было почитать, как работает сессия PHP на самом деле (en). Оказалось, что при закрытии сессии всегда вызвается SessionHandlerInterface::write(), не зависимо от того, изменились ли данные в сессионном объекте. Я это учел, и в моей реализации выполняется проверка, прежде чем выполнять сохранение в БД.

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

А вот для чего все эти инструменты не подходят, так это для добавления новых методов в механизм работы сессий. Клиент-то работает с $_SESSION, а не с каким-то классом, см. Session Basic usage. Все вызовы нужных методов скрыты от клиента, он просто выполняет чтение/запись в переменную-массив. Даже если клиент задействует напрямую какие-то методы, типа php::session_start(), к классовым методам нет такого неявного доступа.

Архив с исходниками моей реализации. Класс модели, которую я там использовал, опирается на движок Kira в его текущей dev-версии. Вы можете рассматривать эту модель, как пвсевдокод, там ничего сложного.

Дополнительные заметки

Данные в сессии сериализованы, но это не тот же самый результат, что при php:serialize(). Вообще формат зависит от настройки session.serialize-handler.

В сравнении, обычная сериализация и то, что по дефолту в сессии:

$_SESSION['test']  = 'summer';
// test|s:6:"summer";

echo serialize(['test' => 'summer']);
// "a:1:{s:4:"test";s:6:"summer";}"

Это значит, что не нужно пытаться вручную менять ланшафты изменять значение в сессионных данных. Если настройка session.serialize-handler поменяется, формат будет другой.


У меня был баг в реализации, возникало исключение в вызове SessionHandlerInterface::write() и оно почему-то шло мимо кастомного перехватчика и отрисовывалось, как есть в PHP, черно-оранжевая таблица. А это значит, никакого логирования или уведомления админу или любой другой кастомной реакции на исключение.

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

[1oo%, EoF]

Понравилась статья? Расскажите о ней друзьям:

Метки: PHP, кодинг

Комментарии
Для работы модуля комментариев включите javaScript


Показать/скрыть правила
Имя
[i] [b] [u] [s] [url]
:-) ;-) :D *lol* 8-) :-* :-| :-( *cry* :o :-? *unsure* *oops* :-x *shocked* *zzz* :P *evil*

Осталось 1000 символов.
Код защиты от спама Обновить код
Каждый комментарий проходит ручную модерацию. 100% фильтрация спама.
Продвижение
Время
Метки