Хранение PHP-сессий в базе данных
Подход, позволяющий хранить PHP-сессии в базе данных вместо файлов
Начну сразу с причин, по которым я пишу эту статью. Я периодически просматриваю лог запросов, по которому люди попадают сюда, и вот один из запросов — хранить php сессию в mysql
.
Итак, как же хранить PHP-сессии в базе данных?
На самом деле, в этом нет ничего сложного: в PHP есть одна полезная функция — session_set_save_handler — которая и выполняет всю грязную работу:
session_set_save_handler() sets the user-level session storage functions which are used for storing and retrieving data associated with a session. This is most useful when a storage method other than those supplied by PHP sessions is preferred. i.e. Storing the session data in a local database.
Эта функция принимает шесть аргументов типа сallback
:
- open — вызывается при открытии/создании сессии;
- close — вызывается при закрытии сессии (например, чтобы приложение могло закрыть файл);
- read — чтение сессии;
- write — запись сессии;
- destroy — уничтожение сессии (
session_destroy
); - gc — "сборка мусора"
Все функции (кроме read
) должны возвращать true
, если все прошло успешно и false
в противном случае.
Для хранения сессии у нас есть такая таблица:
`id` CHARACTER(32) BINARY NOT NULL PRIMARY KEY, /* Session ID */
`expires` INTEGER NOT NULL, /* Время истекания сессии */
`session_data` TEXT NOT NULL, /* Данные, хранящиеся в сессии */
KEY(`expires`)
)
Один маленький нюанс: если в MySQL делать таблицу сессий типа MEMORY (т.е. задать ей такой storage engine), то могут возникнуть проблемы с удалением записей при сборке мусора, ибо MEMORY storage engine не может использовать индексы для операций сравнения типа "больше"/"меньше".
Для абстракции от конкретного SQL-сервера, будем считать, что у нас имеется некий класс Persistent
, обладающий способностями загружать/сохранять данные в базу данных.
Таким образом, реализация класса Session
будет иметь следующий вид:
require_once('class.Persistent.php');
class Session extends Persistent
{
/**
* @var string
*/
public $id;
/**
* @var int
*/
public $expires;
/**
* @var string
*/
public $session_data;
/**
* @var bool
*/
public $m_new;
function __contruct($data)
{
parent::__construct($data);
}
static function getTable()
{
return TABLE_SESSION; //константа, задающая имя таблицы сессий
}
}
?>
Пока все предельно просто. О переменной $m_new
поговорим позже.
Теперь собственно реализация класса, управляющего се