Як використовувати 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, щоб отримувати сповіщення, коли відбуватиметься така помилка.