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

Кеш

Использование кэша - прекрасный способ ускорить ваше приложение. Компонент Symfony cache поставляется с множеством адаптеров для разных хранилищ. Каждый адаптер разработан для высокой производительности.

Следующий пример показывает типичное использование кэша:

use Symfony\Contracts\Cache\ItemInterface;

// Вызываемое будет запущено только при отсутствии значения в кэше
$value = $pool->get('my_cache_key', function (ItemInterface $item) {
    $item->expiresAfter(3600);

    // ... сделать HTTP запрос или сложные вычисления
    $computedValue = 'foobar';

    return $computedValue;
});

echo $value; // 'foobar'

// ... и удалить ключ кеша
$pool->delete('my_cache_key');

Symfony поддерживает Cache Contracts, PSR-6/16 и интерфейсы Doctrine Cache. Вы можете прочитать больше о них в документации компонента.

Deprecated since version 5.4: Поддержка Doctrine Cache устарела в Symfony 5.4, и будет удалена в Symfony 6.0.

Настройка кэша с FrameworkBundle

Когда настраиваете компонент кэша есть несколько концепций, о которых нужно знать:

Пул
Это сервис с которым вы будете взаимодействовать. Каждый пул будет всегда иметь своё пространство имён и закешированные элементы. Не бывает конфликтов между разными пулами.
Адаптер
Адаптер - это шаблон, который вы используете для создания пула.
Провайдер
Провайдер - это сервис, который адаптеры используют для подключения к хранилищу. Примерами таких адаптеров являются Redis и Memcached. Если как провайдер используется DSN, то автоматически создаётся сервис.

Есть 2 пула, включённые по умолчанию. Это cache.app и cache.system. Системный кэк используется для вещей вроде аннотаций, сериализатора и валидации. cache.app может использоваться в вашем коде. Вы можете настроить какой адаптер (шаблон) они будут использовать используя app и system ключи как:

  • YAML
    1
    2
    3
    4
    5
    # config/packages/cache.yaml
    framework:
        cache:
            app: cache.adapter.filesystem
            system: cache.adapter.system
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/cache.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:cache app="cache.adapter.filesystem"
                system="cache.adapter.system"
            />
        </framework:config>
    </container>
    
  • PHP
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // config/packages/cache.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->cache()
            ->app('cache.adapter.filesystem')
            ->system('cache.adapter.system')
        ;
    };
    

Компонент Cache поставляется с набором сконфигурированных адаптеров:

New in version 5.2: cache.adapter.redis_tag_aware был представлен в Symfony 5.2.

Некоторые из этих адаптеров могут быть настроены с помощью сокращений. При использовании этих сокращений создадутся пулы с id сервисов вида cache.[type].

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    # config/packages/cache.yaml
    framework:
        cache:
            directory: '%kernel.cache_dir%/pools' # Only used with cache.adapter.filesystem
    
            # service: cache.doctrine
            default_doctrine_provider: 'app.doctrine_cache'
            # service: cache.psr6
            default_psr6_provider: 'app.my_psr6_service'
            # service: cache.redis
            default_redis_provider: 'redis://localhost'
            # service: cache.memcached
            default_memcached_provider: 'memcached://localhost'
            # service: cache.pdo
            default_pdo_provider: 'doctrine.dbal.default_connection'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <!-- config/packages/cache.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>
            <!--
            default_doctrine_provider: Service: cache.doctrine
            default_psr6_provider: Service: cache.psr6
            default_redis_provider: Service: cache.redis
            default_memcached_provider: Service: cache.memcached
            default_pdo_provider: Service: cache.pdo
            -->
            <!-- "directory" attribute is only used with cache.adapter.filesystem -->
            <framework:cache directory="%kernel.cache_dir%/pools"
                default_doctrine_provider="app.doctrine_cache"
                default_psr6_provider="app.my_psr6_service"
                default_redis_provider="redis://localhost"
                default_memcached_provider="memcached://localhost"
                default_pdo_provider="doctrine.dbal.default_connection"
            />
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    // config/packages/cache.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->cache()
            // Only used with cache.adapter.filesystem
            ->directory('%kernel.cache_dir%/pools')
            // Service: cache.doctrine
            ->defaultDoctrineProvider('app.doctrine_cache')
            // Service: cache.psr6
            ->defaultPsr6Provider('app.my_psr6_service')
            // Service: cache.redis
            ->defaultRedisProvider('redis://localhost')
            // Service: cache.memcached
            ->defaultMemcachedProvider('memcached://localhost')
            // Service: cache.pdo
            ->defaultPdoProvider('doctrine.dbal.default_connection')
        ;
    };
    

Deprecated since version 5.4: Опция default_doctrine_provider устарела в Symfony 5.4, и будет удалена в Symfony 6.0.

Создание пользовательских пулов (с пространством имён)

Вы также можете создать пулы с другими настройками:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # config/packages/cache.yaml
    framework:
        cache:
            default_memcached_provider: 'memcached://localhost'
    
            pools:
                # создаст сервис "custom_thing.cache"
                # автоподключаемый через "CacheInterface $customThingCache"
                # использует конфигурацию кэша "app"
                custom_thing.cache:
                    adapter: cache.app
    
                # создаёт сервис "my_cache_pool"
                # автоподключаемый через "CacheInterface $myCachePool"
                my_cache_pool:
                    adapter: cache.adapter.filesystem
    
                # использует настройку выше default_memcached_provider
                acme.cache:
                    adapter: cache.adapter.memcached
    
                # управление настройками адаптера
                foobar.cache:
                    adapter: cache.adapter.memcached
                    provider: 'memcached://user:[email protected]'
    
                # использует пул "foobar.cache" как бекенд, но настраивает
                # время жизни и как другие пулы выше имеет собственное пространство имён элементов кэша
                short_cache:
                    adapter: foobar.cache
                    default_lifetime: 60
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <!-- config/packages/cache.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:cache default-memcached-provider="memcached://localhost">
                <!-- создает сервис "custom_thing.cache",
                     автомонтируемый с помощью "CacheInterface $customThingCache"
                     использует конфигурацию кеша "app" -->
                <framework:pool name="custom_thing.cache" adapter="cache.app"/>
    
                <!-- создает сервис "my_cache_pool",
                     автомонтируемый с помощью "CacheInterface $myCachePool" -->
                <framework:pool name="my_cache_pool" adapter="cache.adapter.filesystem"/>
    
                <!-- использует вышеуказанный default_memcached_provider -->
                <framework:pool name="acme.cache" adapter="cache.adapter.memcached"/>
    
                <!-- контролируйте конфигурацию адаптера -->
                <framework:pool name="foobar.cache" adapter="cache.adapter.memcached"
                    provider="memcached://user:[email protected]"
                />
    
                <!-- использует пул "foobar.cache" в качестве бекэнда, но контролирует
                     жизненный цикл, и (как и все пулы), имеет отдельное пространство имен кеша -->
                <framework:pool name="short_cache" adapter="foobar.cache" default-lifetime="60"/>
            </framework:cache>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    // config/packages/cache.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $cache = $framework->cache();
        $cache->defaultMemcachedProvider('memcached://localhost');
    
        // создает сервис "custom_thing.cache", автомонтируемый
        // с помощью "CacheInterface $customThingCache"
        // использует конфигурацию кеша "app"
        $cache->pool('custom_thing.cache')
            ->adapters(['cache.app']);
    
        // создает сервис "my_cache_pool", автомонтируемый
        // с помощью "CacheInterface $myCachePool"
        $cache->pool('my_cache_pool')
            ->adapters(['cache.adapter.filesystem']);
    
        // использует вышеназванный default_memcached_provider
        $cache->pool('acme.cache')
            ->adapters(['cache.adapter.memcached']);
    
         // контролируйте конфигурацию адаптера
        $cache->pool('foobar.cache')
            ->adapters(['cache.adapter.memcached'])
            ->provider('memcached://user:[email protected]');
    
        $cache->pool('short_cache')
            ->adapters(['foobar.cache'])
            ->defaultLifetime(60);
    };
    

Каждый пул управляет набором независимых ключей кэша: ключи из разных пулов никогда не пересекаются, даже, если они используют один и тот же бекэнд. Это достигается добавлением префиксов к ключам с пространством имён, которое генерируется хешированием названия пула, имени скомпилированного класса контейнера и настраиваемым seed который по умолчанию равняется каталогу проекта.

Каждый кастомный пул становится сервисом, чей id является именем пула (например, custom_thing.cache). Алиас для автоподключения также создайтся для каждого пула используя camel case версию его имени - например custom_thing.cache может автовнедряться при названии аргумента $customThingCache с типом CacheInterface или Psr\Cache\CacheItemPoolInterface:

use Symfony\Contracts\Cache\CacheInterface;

// в методе контроллера
public function listProducts(CacheInterface $customThingCache)
{
    // ...
}

// в сервисе
public function __construct(CacheInterface $customThingCache)
{
    // ...
}

Tip

Если вам нужно, чтобы пространтво имен было интероперабельно со сторонним приложением, то вы можете контролировать авто-генерирование, установив атрибут namespace сервисного тега cache.pool. К примеру, вы можете переопределить сервисное определение адаптера:

  • YAML
    1
    2
    3
    4
    5
    6
    # config/services.yaml
    services:
        app.cache.adapter.redis:
            parent: 'cache.adapter.redis'
            tags:
                - { name: 'cache.pool', namespace: 'my_custom_namespace' }
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    <!-- 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="app.cache.adapter.redis" parent="cache.adapter.redis">
                <tag name="cache.pool" namespace="my_custom_namespace"/>
            </service>
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    // config/services.php
    namespace Symfony\Component\DependencyInjection\Loader\Configurator;
    
    return function(ContainerConfigurator $configurator) {
        $services = $configurator->services();
    
        $services->set('app.cache.adapter.redis')
            ->parent('cache.adapter.redis')
            ->tag('cache.pool', ['namespace' => 'my_custom_namespace']);
    };
    

Пользовательские настройки провайдеров

Некоторые провайдеры имеют специфические настройки конфигурации. RedisAdapter позволяет вам создавать провайдеров с настройками timeout, retry_interval и так далее. Для использования этих настроек со значениями не по умолчанию нужно создать собственный провайдер \Redis и использовать его при конфигурации пула.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- config/packages/cache.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:cache>
            <framework:pool name="cache.my_redis" adapter="cache.adapter.redis" provider="app.my_custom_redis_provider"/>
        </framework:cache>
    </framework:config>

    <services>
        <service id="app.my_custom_redis_provider" class="\Redis">
            <factory class="Symfony\Component\Cache\Adapter\RedisAdapter" method="createConnection"/>
            <argument>redis://localhost</argument>
            <argument type="collection">
                <argument key="retry_interval">2</argument>
                <argument key="timeout">10</argument>
            </argument>
        </service>
    </services>
</container>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// config/packages/cache.php
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Config\FrameworkConfig;

return static function (ContainerBuilder $container, FrameworkConfig $framework) {
    $framework->cache()
        ->pool('cache.my_redis')
            ->adapters(['cache.adapter.redis'])
            ->provider('app.my_custom_redis_provider');


    $container->register('app.my_custom_redis_provider', \Redis::class)
        ->setFactory([RedisAdapter::class, 'createConnection'])
        ->addArgument('redis://localhost')
        ->addArgument([
            'retry_interval' => 2,
            'timeout' => 10
        ])
    ;
};

Создание цепочки кэшей

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

Цепочка кэшей объединяет несколько пулов кэшей в один. При сохранении элемента в цепочку кэшей Symfony сохраняет его последовательно во все пулы. При получении элемента Symfony пытается получить его из первого пула. Если он не найден, пробует следующие пулы пока не найдёт элемент или не выбросится исключение. Из-за такого поведения рекомендуется определять адаптеры в цепочке начиная с самого быстрого и заканчивая самым медленным.

Если случается ошибка при сохранении элемента в пул, Symfony сохраняет его в других пулах и не выбрасывается исключение. Позже, при получении элемента, Symfony автоматически сохраняет элемент во всех недостающих пулах.

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    # config/packages/cache.yaml
    framework:
        cache:
            pools:
                my_cache_pool:
                    default_lifetime: 31536000  # One year
                    adapters:
                      - cache.adapter.array
                      - cache.adapter.apcu
                      - {name: cache.adapter.redis, provider: 'redis://user:[email protected]'}
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <!-- config/packages/cache.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">
    
        <framework:config>
            <framework:cache>
                <framework:pool name="my_cache_pool" default-lifetime="31536000">
                    <framework:adapter name="cache.adapter.array"/>
                    <framework:adapter name="cache.adapter.apcu"/>
                    <framework:adapter name="cache.adapter.redis" provider="redis://user:[email protected]"/>
                </framework:pool>
            </framework:cache>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    // config/packages/cache.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->cache()
            ->pool('my_cache_pool')
                ->defaultLifetime(31536000) // One year
                ->adapters([
                    'cache.adapter.array',
                    'cache.adapter.apcu',
                    ['name' => 'cache.adapter.redis', 'provider' => 'redis://user:[email protected]'],
                ])
        ;
    };
    

Использование тегов кеша

В приложениях с большим количеством элементов может быть полезно организовать сохранённые данные чтобы более эффективно инвалидировать кэш. Один из вариантов - использовать теги кэша. К элементу кэша можно добавить один или несколько тегов. Все элементы с тем же тегом могут быть инвалидированы с помощью вызова одной функции:

use Symfony\Contracts\Cache\ItemInterface;
use Symfony\Contracts\Cache\TagAwareCacheInterface;

class SomeClass
{
    private $myCachePool;

    // используем автоподключение для внедрения пула кэша
    public function __construct(TagAwareCacheInterface $myCachePool)
    {
        $this->myCachePool = $myCachePool;
    }

    public function someMethod()
    {
        $value0 = $this->myCachePool->get('item_0', function (ItemInterface $item) {
            $item->tag(['foo', 'bar']);

            return 'debug';
        });

        $value1 = $this->myCachePool->get('item_1', function (ItemInterface $item) {
            $item->tag('foo');

            return 'debug';
        });

        // Удалить все элементы ключа с тегом "bar"
        $this->myCachePool->invalidateTags(['bar']);
    }
}

Чтобы эта фича работала, нужно, чтобы адаптер кэша реализовал интерфейс TagAwareCacheInterface. Тогда можно использовать следующую настройку.

  • YAML
    1
    2
    3
    4
    5
    6
    7
    # config/packages/cache.yaml
    framework:
        cache:
            pools:
                my_cache_pool:
                    adapter: cache.adapter.redis
                    tags: true
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    <!-- config/packages/cache.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:cache>
              <framework:pool name="my_cache_pool" adapter="cache.adapter.redis" tags="true"/>
            </framework:cache>
        </framework:config>
    </container>
    
  • YAML
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # config/packages/cache.yaml
    framework:
        cache:
            pools:
                my_cache_pool:
                    adapter: cache.adapter.redis
                    tags: tag_pool
                tag_pool:
                    adapter: cache.adapter.apcu
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    <!-- config/packages/cache.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">
    
        <framework:config>
            <framework:cache>
              <framework:pool name="my_cache_pool" adapter="cache.adapter.redis" tags="tag_pool"/>
              <framework:pool name="tag_pool" adapter="cache.adapter.apcu"/>
            </framework:cache>
        </framework:config>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    // config/packages/cache.php
    use Symfony\Config\FrameworkConfig;
    
    return static function (FrameworkConfig $framework) {
        $framework->cache()
            ->pool('my_cache_pool')
                ->tags('tag_pool')
                ->adapters(['cache.adapter.redis'])
        ;
    
        $framework->cache()
            ->pool('tag_pool')
                ->adapters(['cache.adapter.apcu'])
        ;
    };
    

Note

Интерфейс TagAwareCacheInterface при автоподключении использует сервис cache.app.

Очистка кэша

Для очистки кэша можно использовать команду bin/console cache:pool:clear [pool]. Это удалит все записи из вашего хранилища и нужно будет пересчитать все значения. Вы также можете сгруппировать ваши пулы в “очистители кэша”. По умолчанию есть 3 очистителя кэша:

  • cache.global_clearer
  • cache.system_clearer
  • cache.app_clearer

Глобальный очиститель удалит все элементы кэша в каждом пуле. Системный очиститель кэша используется при команде bin/console cache:clear. App clearer - это очиститель по умолчанию.

Для просмотра всех доступных пулов кэша:

1
$ php bin/console cache:pool:list

Очистить один пул:

1
$ php bin/console cache:pool:clear my_cache_pool

Очистить все пользовательские пулы:

1
$ php bin/console cache:pool:clear cache.app_clearer

Очистить все кэши везде:

1
$ php bin/console cache:pool:clear cache.global_clearer

Шифрование кэша

New in version 5.1: Класс SodiumMarshaller был представлен в Symfony 5.1.

Для того, чтобы зашифровать кэш, используя libsodium, вы можете использовать SodiumMarshaller.

Для начала, вам нужно сгенерировать безопасный ключ и добавить его в свой secret store в виде CACHE_DECRYPTION_KEY:

1
$ php -r 'echo base64_encode(sodium_crypto_box_keypair());'

Затем, зарегистрируйте сервис SodiumMarshaller, используя этот ключ:

  • YAML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # config/packages/cache.yaml
    
    # ...
    services:
        Symfony\Component\Cache\Marshaller\SodiumMarshaller:
            decorates: cache.default_marshaller
            arguments:
                - ['%env(base64:CACHE_DECRYPTION_KEY)%']
                # используйте несколько ключей, чтобы менять их
                #- ['%env(base64:CACHE_DECRYPTION_KEY)%', '%env(base64:OLD_CACHE_DECRYPTION_KEY)%']
                - '@Symfony\Component\Cache\Marshaller\SodiumMarshaller.inner'
    
  • XML
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!-- config/packages/cache.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">
    
        <!-- ... -->
    
        <services>
            <service id="Symfony\Component\Cache\Marshaller\SodiumMarshaller" decorates="cache.default_marshaller">
                <argument type="collection">
                    <argument>env(base64:CACHE_DECRYPTION_KEY)</argument>
                    <!-- use multiple keys in order to rotate them -->
                    <!-- <argument>env(base64:OLD_CACHE_DECRYPTION_KEY)</argument> -->
                </argument>
                <argument type="service" id="Symfony\Component\Cache\Marshaller\SodiumMarshaller.inner"/>
            </service>
        </services>
    </container>
    
  • PHP
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    // config/packages/cache.php
    use Symfony\Component\Cache\Marshaller\SodiumMarshaller;
    use Symfony\Component\DependencyInjection\ChildDefinition;
    use Symfony\Component\DependencyInjection\Reference;
    
    // ...
    $container->setDefinition(SodiumMarshaller::class, new ChildDefinition('cache.default_marshaller'))
        ->addArgument(['env(base64:CACHE_DECRYPTION_KEY)'])
        // use multiple keys in order to rotate them
        //->addArgument(['env(base64:CACHE_DECRYPTION_KEY)', 'env(base64:OLD_CACHE_DECRYPTION_KEY)'])
        ->addArgument(new Reference(SodiumMarshaller::class.'.inner'));
    

Caution

Это зашифрует значения объектов кэша, но не ключи кэша. Будьте осторожны, чтобы не допустить утечки конфиденциальных данных в ключах кэша.

При конфигурации нескольких ключей, первый ключ будет использоваться для чтения и записи, а дополнительный(е) ключ(и) будут использоваться только для чтения. Когдща все объекты кэша будут зашифрованы, а у старого ключа истечет срок годности, вы можете полностью удалить OLD_CACHE_DECRYPTION_KEY.

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