Дата обновления перевода 2021-12-25

Сессии

Symfony предоставляет объект сессий и несколько утилит, которые вы можете использовать для хранения информации о пользователе между запросами.

Конфигурация

Сессии предоставляются компонентом HttpFoundation, который включен во все приложения Symfony, независимо от того, как вы ее устанавливали. До использования сессий, посмотрите на конфигурацию по умолчанию:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # config/packages/framework.yaml
    framework:
        session:
            # включает поддержку сессий в приложении
            enabled: true
            # ID сервиса, используемого для хранения сессий.
            # NULL означает, что Symfony по умолчанию использует PHP-механизм
            handler_id: null
            # улучшает безопасность куки, используемых для сессии
            cookie_secure: 'auto'
            cookie_samesite: 'lax'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <!--
                enabled: включает поддержку сессий в приложении
                handler-id: ID сервиса, используемого для хранения сессий
                            NULL означает, что Symfony по умолчанию использует PHP-механизм
                cookie-secure and cookie-samesite: улучшает безопасность куки, используемых для сессии
            -->
            <framework:session enabled="true"
                               handler-id="null"
                               cookie-secure="auto"
                               cookie-samesite="lax"/>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // config/packages/framework.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->session()
            // включает поддержку сессий в приложении
            ->enabled(true)
            // ID сервиса, используемого для хранения сессий
            // NULL означает, что Symfony по умолчанию использует PHP-механизм
            ->handlerId(null)
            // улучшает безопасность куки, используемых для сессии
            ->cookieSecure('auto')
            ->cookieSamesite('lax')
        ;
    };
    

Установки опции конфигурации handler_id как null, означает, что Symfony будет использовать нативный PHP-механизм сессий. Файлы метаданных сессии будут храниться вне приложения Symfony, в каталоге, управлемом PHP. Хотя это обычно все упрощает, некоторые опции срока годности сессий могут работать не так, как ожидается, если другие приложения, пишущиеся в тот же каталог, имеют настройки короткого максимального жизненного цикла.

Если вы хотите, вы можете использовать сервис session.handler.native_file в качестве handler_id, чтобы позволить Symfony управлять сессиями самостоятельно. Другая полезная опция - save_path, которая определяет каталог, в котором Symfony будет хранить файлы метаданных сессии:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/packages/framework.yaml
    framework:
        session:
            # ...
            handler_id: 'session.handler.native_file'
            save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- config/packages/framework.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:framework="http://symfony.com/schema/dic/symfony"
        xsi:schemaLocation="http://symfony.com/schema/dic/services
            https://symfony.com/schema/dic/services/services-1.0.xsd
            http://symfony.com/schema/dic/symfony https://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
    
        <framework:config>
            <framework:session enabled="true"
                               handler-id="session.handler.native_file"
                               save-path="%kernel.project_dir%/var/sessions/%kernel.environment%"/>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    // config/packages/framework.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->session()
            // ...
            ->handlerId('session.handler.native_file')
            ->savePath('%kernel.project_dir%/var/sessions/%kernel.environment%')
        ;
    };
    

Посмотрите справочник конфигурации Symfony, чтобы узнать больше о других доступных опциях конфигурации Сессии. Вы также можете хранить сессии в базе данных.

Базовое применение

Сессия доступна через Request и RequestStack. Symfony предоставляет сервис request_stack, который внедряется в ваши сервисы и контроллеры, если вы используете в аргументе подсказку RequestStack:

use Symfony\Component\HttpFoundation\RequestStack;

class SomeService
{
    private $requestStack;

    public function __construct(RequestStack $requestStack)
    {
        $this->requestStack = $requestStack;
    }

    public function someMethod()
    {
        $session = $this->requestStack->getSession();

        // сохраняет атрибут в сессии для дальнейшего повторного использования
        $session->set('attribute-name', 'attribute-value');

        // получает атрибут по имени
        $foo = $session->get('foo');

        // второй аргумент - это значение, возвращенное, если атрибут не существует
        $filters = $session->get('filters', []);

        // ...
    }
}

Deprecated since version 5.3: Сервисы SessionInterface и session устарели в Symfony 5.3. Вместо них, внедрите сервис RequestStack, чтобы получить объект сессии для текущего запроса.

Сохраненные атрибуты остаются в сессии до конца этой сессии пользователя. По умолчанию, атрибуты сессии - это пары ключ-значение, управляеыые классом AttributeBag.

Deprecated since version 5.3: Класс NamespacedAttributeBag устарел в Symfony 5.3. Если вам нужна эта функция, вам нужно будет реализовать класс самостоятельно.

Если ваши приложения сложнее, вам может быть лучше использовать атрибуты сессий с пространством имен, которые управляются классом NamespacedAttributeBag. Перед тем, как их использовать, переопределите определение сервиса session_listener, чтобы создать ваш объект Session со значением по умолчанию AttributeBag от NamespacedAttributeBag:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    # config/services.yaml
    session.factory:
        autoconfigure: true
        class: App\Session\SessionFactory
        arguments:
        - '@request_stack'
        - '@session.storage.factory'
        - ['@session_listener', 'onSessionUsage']
        - '@session.namespacedattributebag'
    
    session.namespacedattributebag:
        class: Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- config/services.xml -->
    <?xml version="1.0" encoding="UTF-8" ?>
    <container xmlns="http://symfony.com/schema/dic/services"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd">
    
        <services>
            <service id="session" class="Symfony\Component\HttpFoundation\Session\Session" public="true">
                <argument type="service" id="session.storage"/>
                <argument type="service" id="session.namespacedattributebag"/>
                <argument type="service" id="session.flash_bag"/>
            </service>
    
            <service id="session.namespacedattributebag"
                class="Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag"
            />
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag;
    use Symfony\Component\HttpFoundation\Session\Session;
    
    return function(ContainerConfigurator $configurator) {
        $services = $configurator->services();
    
        $services->set('session', Session::class)
            ->public()
            ->args([
                ref('session.storage'),
                ref('session.namespacedattributebag'),
                ref('session.flash_bag'),
            ])
        ;
    
        $services->set('session.namespacedattributebag', NamespacedAttributeBag::class);
    };
    

Избегайте запуска сессий для анонимных пользователей

Сессии автоматически запускаются каждый раз, когда вы читаете, пишете или просто проверяете существование данных в сессии. Это может навредить производительности вашего приложения, так как все пользователи получат куки сессии. Для того, чтобы предотвратить это, вы должны полностью избежать доступа к сессии.

Эта документация является переводом официальной документации Symfony и предоставляется по свободной лицензии CC BY-SA 3.0.