Cache

    The following example shows a typical usage of the cache:

    Symfony supports the Cache Contracts, PSR-6/16 and Doctrine Cache interfaces.You can read more about these at the component documentation.

    New in version 4.2: The cache contracts were introduced in Symfony 4.2.

    When configuring the cache component there are a few concepts you should knowof:

    • Pool
    • This is a service that you will interact with. Each pool will always haveits own namespace and cache items. There is never a conflict between pools.
    • Adapter
    • An adapter is a template that you use to create Pools.
    • Provider
    • A provider is a service that some adapters are using to connect to the storage.Redis and Memcached are example of such adapters. If a DSN is used as theprovider then a service is automatically created.There are two pools that are always enabled by default. They are andcache.system. The system cache is used for things like annotations, serializer,and validation. The cache.app can be used in your code. You can configure whichadapter (template) they use by using the app and system key like:
    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. app: cache.adapter.filesystem
    5. system: cache.adapter.system
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache app="cache.adapter.filesystem"
    11. system="cache.adapter.system"
    12. />
    13. </framework:config>
    14. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. 'app' => 'cache.adapter.filesystem',
    5. 'system' => 'cache.adapter.system',
    6. ],
    7. ]);

    The Cache component comes with a series of adapters pre-configured:

    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. directory: '%kernel.cache_dir%/pools' # Only used with cache.adapter.filesystem
    5.  
    6. # service: cache.doctrine
    7. default_doctrine_provider: 'app.doctrine_cache'
    8. # service: cache.psr6
    9. default_psr6_provider: 'app.my_psr6_service'
    10. # service: cache.redis
    11. default_redis_provider: 'redis://localhost'
    12. # service: cache.memcached
    13. default_memcached_provider: 'memcached://localhost'
    14. # service: cache.pdo
    15. default_pdo_provider: 'doctrine.dbal.default_connection'
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <!--
    11. default_doctrine_provider: Service: cache.doctrine
    12. default_psr6_provider: Service: cache.psr6
    13. default_redis_provider: Service: cache.redis
    14. default_memcached_provider: Service: cache.memcached
    15. default_pdo_provider: Service: cache.pdo
    16. -->
    17. <framework:cache directory="%kernel.cache_dir%/pools"
    18. default_doctrine_provider="app.doctrine_cache"
    19. default_psr6_provider="app.my_psr6_service"
    20. default_redis_provider="redis://localhost"
    21. default_memcached_provider="memcached://localhost"
    22. default_pdo_provider="doctrine.dbal.default_connection"
    23. />
    24. </framework:config>
    25. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. // Only used with cache.adapter.filesystem
    5. 'directory' => '%kernel.cache_dir%/pools',
    6.  
    7. // Service: cache.doctrine
    8. 'default_doctrine_provider' => 'app.doctrine_cache',
    9. // Service: cache.psr6
    10. 'default_psr6_provider' => 'app.my_psr6_service',
    11. // Service: cache.redis
    12. 'default_redis_provider' => 'redis://localhost',
    13. // Service: cache.memcached
    14. 'default_memcached_provider' => 'memcached://localhost',
    15. // Service: cache.pdo
    16. 'default_pdo_provider' => 'doctrine.dbal.default_connection',
    17. ],
    18. ]);

    Creating Custom (Namespaced) Pools

    You can also create more customized pools:

    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. default_memcached_provider: 'memcached://localhost'
    5.  
    6. pools:
    7. # creates a "custom_thing.cache" service
    8. # autowireable via "CacheInterface $customThingCache"
    9. # uses the "app" cache configuration
    10. custom_thing.cache:
    11. adapter: cache.app
    12.  
    13. # creates a "my_cache_pool" service
    14. # autowireable via "CacheInterface $myCachePool"
    15. my_cache_pool:
    16. adapter: cache.adapter.array
    17.  
    18. # uses the default_memcached_provider from above
    19. acme.cache:
    20. adapter: cache.adapter.memcached
    21.  
    22. # control adapter's configuration
    23. foobar.cache:
    24. adapter: cache.adapter.memcached
    25. provider: 'memcached://user:[email protected]'
    26.  
    27. # uses the "foobar.cache" pool as its backend but controls
    28. # the lifetime and (like all pools) has a separate cache namespace
    29. short_cache:
    30. default_lifetime: 60
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache default_memcached_provider="memcached://localhost">
    11. <framework:pool name="custom_thing.cache" adapter="cache.app"/>
    12. <framework:pool name="my_cache_pool" adapter="cache.adapter.array"/>
    13. <framework:pool name="acme.cache" adapter="cache.adapter.memcached"/>
    14. <framework:pool name="foobar.cache" adapter="cache.adapter.memcached" provider="memcached://user:"/>
    15. <framework:pool name="short_cache" adapter="foobar.cache" default_lifetime="60"/>
    16. </framework:cache>
    17. </framework:config>
    18. </container>
    • PHP

    Each pool manages a set of independent cache keys: keys of different poolsnever collide, even if they share the same backend. This is achieved by prefixingkeys with a namespace that's generated by hashing the name of the pool, the nameof the compiled container class and a configurable seedthat defaults to the project directory.

    Each custom pool becomes a service where the service id is the name of the pool(e.g. custom_thing.cache). An autowiring alias is also created for each poolusing the camel case version of its name - e.g. custom_thing.cache can beinjected automatically by naming the argument $customThingCache and type-hinting itwith either orPsr\Cache\CacheItemPoolInterface:

    1. use Symfony\Contracts\Cache\CacheInterface;
    2.  
    3. // from a controller method
    4. public function listProducts(CacheInterface $customThingCache)
    5. {
    6. // ...
    7. }
    8.  
    9. // in a service
    10. public function __construct(CacheInterface $customThingCache)
    11. {
    12. // ...
    13. }

    Some providers have specific options that can be configured. The allows you tocreate providers with option timeout, retry_interval. etc. To use theseoptions with non-default values you need to create your own \Redis providerand use that when configuring the pool.

    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. pools:
    5. cache.my_redis:
    6. adapter: cache.adapter.redis
    7. provider: app.my_custom_redis_provider
    8.  
    9. services:
    10. app.my_custom_redis_provider:
    11. class: \Redis
    12. factory: ['Symfony\Component\Cache\Adapter\RedisAdapter', 'createConnection']
    13. arguments:
    14. - 'redis://localhost'
    15. - { retry_interval: 2, timeout: 10 }
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache>
    11. <framework:pool name="cache.my_redis" adapter="cache.adapter.redis" provider="app.my_custom_redis_provider"/>
    12. </framework:cache>
    13. </framework:config>
    14.  
    15. <services>
    16. <service id="app.my_custom_redis_provider" class="\Redis">
    17. <argument>redis://localhost</argument>
    18. <argument type="collection">
    19. <argument key="retry_interval">2</argument>
    20. <argument key="timeout">10</argument>
    21. </argument>
    22. </service>
    23. </services>
    24. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. 'pools' => [
    5. 'cache.my_redis' => [
    6. 'adapter' => 'cache.adapter.redis',
    7. 'provider' => 'app.my_custom_redis_provider',
    8. ],
    9. ],
    10. ],
    11. ]);
    12.  
    13. $container->getDefinition('app.my_custom_redis_provider', \Redis::class)
    14. ->addArgument('redis://localhost')
    15. ->addArgument([
    16. 'retry_interval' => 2,
    17. 'timeout' => 10
    18. ]);

    Creating a Cache Chain

    Different cache adapters have different strengths and weaknesses. Some might be reallyquick but small and some may be able to contain a lot of data but are quite slow.To get the best of both worlds you may use a chain of adapters. The idea is tofirst look at the quick adapter and then move on to slower adapters. In the worstcase the value needs to be recalculated.

    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. pools:
    5. my_cache_pool:
    6. adapter: cache.adapter.psr6
    7. provider: app.my_cache_chain_adapter
    8. cache.my_redis:
    9. adapter: cache.adapter.redis
    10. provider: 'redis://user:'
    11. cache.apcu:
    12. adapter: cache.adapter.apcu
    13. cache.array:
    14. adapter: cache.adapter.array
    15.  
    16.  
    17. services:
    18. app.my_cache_chain_adapter:
    19. class: Symfony\Component\Cache\Adapter\ChainAdapter
    20. arguments:
    21. - ['@cache.array', '@cache.apcu', '@cache.my_redis']
    22. - 31536000 # One year
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache>
    11. <framework:pool name="my_cache_pool" adapter="cache.adapter.psr6" provider="app.my_cache_chain_adapter"/>
    12. <framework:pool name="cache.my_redis" adapter="cache.adapter.redis" provider="redis://user:[email protected]"/>
    13. <framework:pool name="cache.apcu" adapter="cache.adapter.apcu"/>
    14. <framework:pool name="cache.array" adapter="cache.adapter.array"/>
    15. </framework:cache>
    16. </framework:config>
    17.  
    18. <services>
    19. <service id="app.my_cache_chain_adapter" class="Symfony\Component\Cache\Adapter\ChainAdapter">
    20. <argument type="collection">
    21. <argument type="service" value="cache.array"/>
    22. <argument type="service" value="cache.apcu"/>
    23. </argument>
    24. <argument>31536000</argument>
    25. </service>
    26. </services>
    27. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. 'pools' => [
    5. 'my_cache_pool' => [
    6. 'adapter' => 'cache.adapter.psr6',
    7. 'provider' => 'app.my_cache_chain_adapter',
    8. ],
    9. 'cache.my_redis' => [
    10. 'adapter' => 'cache.adapter.redis',
    11. 'provider' => 'redis://user:',
    12. ],
    13. 'cache.apcu' => [
    14. 'adapter' => 'cache.adapter.apcu',
    15. ],
    16. 'cache.array' => [
    17. 'adapter' => 'cache.adapter.array',
    18. ],
    19. ],
    20. ],
    21. ]);
    22.  
    23. $container->getDefinition('app.my_cache_chain_adapter', \Symfony\Component\Cache\Adapter\ChainAdapter::class)
    24. ->addArgument([
    25. new Reference('cache.array'),
    26. new Reference('cache.apcu'),
    27. new Reference('cache.my_redis'),
    28. ])
    29. ->addArgument(31536000);

    Note

    In this configuration the my_cache_pool pool is using the cache.adapter.psr6adapter and the app.my_cache_chain_adapter service as a provider. That isbecause ChainAdapter does not support the tag. So it is decoratedwith the ProxyAdapter.

    In applications with many cache keys it could be useful to organize the data storedto be able to invalidate the cache more efficient. One way to achieve that is touse cache tags. One or more tags could be added to the cache item. All items withthe same key could be invalidate with one function call:

    1. use Symfony\Contracts\Cache\ItemInterface;
    2. use Symfony\Contracts\Cache\TagAwareCacheInterface;
    3.  
    4. class SomeClass
    5. {
    6. private $myCachePool;
    7.  
    8. // using autowiring to inject the cache pool
    9. public function __construct(TagAwareCacheInterface $myCachePool)
    10. {
    11. $this->myCachePool = $myCachePool;
    12. }
    13.  
    14. public function someMethod()
    15. {
    16. $value0 = $this->myCachePool->get('item_0', function (ItemInterface $item) {
    17. $item->tag(['foo', 'bar']);
    18.  
    19. return 'debug';
    20. });
    21.  
    22. $value1 = $this->myCachePool->get('item_1', function (ItemInterface $item) {
    23. $item->tag('foo');
    24.  
    25. return 'debug';
    26. });
    27.  
    28. // Remove all cache keys tagged with "bar"
    29. $this->myCachePool->invalidateTags(['bar']);
    30. }
    31. }

    The cache adapter needs to implement TagAwareCacheInterface`to enable this feature. This could be added by using the following configuration.

    • YAML
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache>
    11. <framework:pool name="my_cache_pool" adapter="cache.adapter.redis" tags="true"/>
    12. </framework:cache>
    13. </framework:config>
    14. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. 'pools' => [
    5. 'my_cache_pool' => [
    6. 'adapter' => 'cache.adapter.redis',
    7. 'tags' => true,
    8. ],
    9. ],
    10. ],
    11. ]);

    Tags are stored in the same pool by default. This is good in most scenarios. Butsometimes it might be better to store the tags in a different pool. That could beachieved by specifying the adapter.

    • YAML
    1. # config/packages/cache.yaml
    2. framework:
    3. cache:
    4. pools:
    5. my_cache_pool:
    6. adapter: cache.adapter.redis
    7. tags: tag_pool
    8. tag_pool:
    9. adapter: cache.adapter.apcu
    • XML
    1. <!-- config/packages/cache.xml -->
    2. <?xml version="1.0" encoding="UTF-8" ?>
    3. <container xmlns="http://symfony.com/schema/dic/services"
    4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5. xmlns:framework="http://symfony.com/schema/dic/symfony"
    6. xsi:schemaLocation="http://symfony.com/schema/dic/services
    7. https://symfony.com/schema/dic/services/services-1.0.xsd">
    8.  
    9. <framework:config>
    10. <framework:cache>
    11. <framework:pool name="my_cache_pool" adapter="cache.adapter.redis" tags="tag_pool"/>
    12. <framework:pool name="tag_pool" adapter="cache.adapter.apcu"/>
    13. </framework:cache>
    14. </framework:config>
    15. </container>
    • PHP
    1. // config/packages/cache.php
    2. $container->loadFromExtension('framework', [
    3. 'cache' => [
    4. 'pools' => [
    5. 'my_cache_pool' => [
    6. 'adapter' => 'cache.adapter.redis',
    7. 'tags' => 'tag_pool',
    8. ],
    9. 'tag_pool' => [
    10. 'adapter' => 'cache.adapter.apcu',
    11. ],
    12. ],
    13. ],
    14. ]);

    Note

    Clearing the Cache

    To clear the cache you can use the bin/console cache:pool:clear [pool] command.That will remove all the entries from your storage and you will have to recalculateall values. You can also group your pools into "cache clearers". There are 3 cacheclearers by default:

    • cache.global_clearer
    • cache.system_clearer
    • cache.app_clearerThe global clearer clears all the cache in every pool. The system cache cleareris used in the command. The app clearer is the defaultclearer.

    To see all available cache pools:

    1. $ php bin/console cache:pool:list

    New in version 4.3: The cache:pool:list command was introduced in Symfony 4.3.

    Clear one pool:

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

    Clear all custom pools:

      Clear all caches everywhere: