Как использовать PdoSessionHandler для хранения сессий в DB
Дата оновлення перекладу 2023-07-05
Как использовать PdoSessionHandler для хранения сессий в DB
Хранилище сессий Symfony по умолчанию хранит информацию о сессиях в файлах. Большинство средних и крупных веб-сайтов используют DB для хранения значений сессий, вместо файлов, поскольку базы данных легче использовать и масштабировать в среде множества веб-серверов.
Symfony имеет встроенное решение для хранения сессий в базах данных, под названием PdoSessionHandler. Чтобы использовать его, зарегистрируйте новый сервис-обработчик:
1 2 3 4 5 6 7 8 9 10 11 12
# config/services.yaml
services:
# ...
Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
arguments:
- 'mysql:dbname=mydatabase'
- { db_username: myuser, db_password: mypassword }
# Если вы используете Doctrine и хотите использовать это соединение повторно, тогда:
# прокомментируйте 2 строки выше и уберите комментарий из строки ниже
# - !service { class: PDO, factory: 'database_connection:getWrappedConnection' }
Далее, скажите Symfony использовать ваш сервис в качестве обработчика сессии:
1 2 3 4 5
# config/packages/framework.yaml
framework:
session:
# ...
handler_id: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
Конфигурация имён таблицы и столбцов
Для этого необходима таблица sessions
с некоторым количеством различных столбцов.
Имя таблицы, а также все имена столбцов, могут быть сконфигурированы путем передачи
второго массива аргументов в PdoSessionHandler
:
1 2 3 4 5 6 7 8
# config/services.yaml
services:
# ...
Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler:
arguments:
- 'mysql:dbname=mydatabase'
- { db_table: sessions, db_username: myuser, db_password: mypassword }
Вот параметры, которые вы можете сконфигурировать:
db_table
(по умолчаниюsessions
):- Имя таблицы сессии в вашей DB;
db_id_col
(по умолчаниюsess_id
):- Имя столбца id в вашей таблице сессии (VARCHAR(128));
db_data_col
(по умолчаниюsess_data
):- Имя столбца значения в вашей таблице сессии (BLOB);
db_time_col
(по умолчаниюsess_time
):- Имя столбца времени в вашей таблице сессии (INTEGER);
db_lifetime_col
(по умолчаниюsess_lifetime
):- Имя столбца жизненного цикла в вашей таблице сессии (INTEGER).
Подготовка DB для хранения сессий
Перед тем, как сохранять сессии в DB, вы должны создать таблицу, которая будет хранить информацию. Обработчик сессий предоставляет метод под названием createTable() для установки этой таблицы за вас, в соответствии с используемым движком DB:
1 2 3 4 5
try {
$sessionHandlerService->createTable();
} catch (\PDOException $e) {
// таблица не могла быть создана по какой-то причине
}
Если вы предпочитаете устанавливать таблицу самостоятельно, то вот некоторые примеры утверждений SQL, которые вы можете использовать в соответствии с вашим конкретным движком DB.
Отличным способом запустить это в производство будет сгенерировать пустую миграцию, а затем добавить внутрь этот SQL:
1
$ php bin/console doctrine:migrations:generate
Найдите правильный SQL ниже и поместите его внутри этого файла. Далее, выполните его из:
1
$ php bin/console doctrine:migrations:migrate
MySQL
1 2 3 4 5 6
CREATE TABLE `sessions` (
`sess_id` VARCHAR(128) NOT NULL PRIMARY KEY,
`sess_data` BLOB NOT NULL,
`sess_time` INTEGER UNSIGNED NOT NULL,
`sess_lifetime` MEDIUMINT NOT NULL
) COLLATE utf8_bin, ENGINE = InnoDB;
Note
Тип столбца BLOB
может хранить максимум 64 килобита. Если данные, хранящиеся в
в сессии пользователя, превысят это значение, может быть вызвано исключение, или
сессия будет тихо восстановлена. Рассмотрите использование MEDIUMBLOB
, если вам
нужно больше места.
PostgreSQL
1 2 3 4 5 6
CREATE TABLE sessions (
sess_id VARCHAR(128) NOT NULL PRIMARY KEY,
sess_data BYTEA NOT NULL,
sess_time INTEGER NOT NULL,
sess_lifetime INTEGER NOT NULL
);
Сервер Microsoft SQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CREATE TABLE [dbo].[sessions](
[sess_id] [nvarchar](255) NOT NULL,
[sess_data] [ntext] NOT NULL,
[sess_time] [int] NOT NULL,
[sess_lifetime] [int] NOT NULL,
PRIMARY KEY CLUSTERED(
[sess_id] ASC
) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Caution
Если данные сессии не помещаются в столбцы данных, они могут быть усечены движком базы данных. Чтобы усугубить ситуацию, когда данные сессии искажаются, PHP начинает игнорировать данные, не предупреждая об этом.
Если приложение хранит большие объемы данных сессии, эта проблема может быть решена путем
увеличения размера столбца (используйте BLOB
или даже MEDIUMBLOB
).
В случае использования MySQL в качестве движка DB, вы можете также активировать
режим строгого SQL, чтобы получать уведомления, когда будет происходить такая ошибка.