The Cache Component

The Cache component provides features covering simple to advanced caching needs.It natively implements PSR-6 and the Cache Contracts for greatestinteroperability. It is designed for performance and resiliency, ships withready to use adapters for the most common caching backends. It enables tag-basedinvalidation and cache stampede protection via locking and early expiration.

Tip

The component also contains adapters to convert between PSR-6, PSR-16 andDoctrine caches. See Adapters For Interoperability between PSR-6 and PSR-16 Cache andDoctrine Cache Adapter.

Installation

  1. $ composer require symfony/cache

Note

If you install this component outside of a Symfony application, you mustrequire the vendor/autoload.php file in your code to enable the classautoloading mechanism provided by Composer. Readthis article for more details.

Cache Contracts versus PSR-6

This component includes two different approaches to caching:

  • PSR-6 Caching:
  • A generic cache system, which involves cache "pools" and cache "items".
  • Cache Contracts:
  • A simpler yet more powerful way to cache values based on recomputation callbacks.

Tip

Using the Cache Contracts approach is recommended: it requires lesscode boilerplate and provides cache stampede protection by default.

Cache Contracts

All adapters support the Cache Contracts. They contain only two methods:get() and delete(). There's no set() method because the get()method both gets and sets the cache values.

The first thing you need is to instantiate a cache adapter. TheFilesystemAdapter is used in thisexample:

  1. use Symfony\Component\Cache\Adapter\FilesystemAdapter;
  2.  
  3. $cache = new FilesystemAdapter();

Now you can retrieve and delete cached data using this object. The firstargument of the get() method is a key, an arbitrary string that youassociate to the cached value so you can retrieve it later. The second argumentis a PHP callable which is executed when the key is not found in the cache togenerate and return the value:

  1. use Symfony\Contracts\Cache\ItemInterface;
  2.  
  3. // The callable will only be executed on a cache miss.
  4. $value = $cache->get('my_cache_key', function (ItemInterface $item) {
  5. $item->expiresAfter(3600);
  6.  
  7. // ... do some HTTP request or heavy computations
  8. $computedValue = 'foobar';
  9.  
  10. return $computedValue;
  11. });
  12.  
  13. echo $value; // 'foobar'
  14.  
  15. // ... and to remove the cache key
  16. $cache->delete('my_cache_key');

Note

Use cache tags to delete more than one key at the time. Read more atCache Invalidation.

The Cache Contracts also comes with built in Stampede prevention. This willremove CPU spikes at the moments when the cache is cold. If an example applicationspends 5 seconds to compute data that is cached for 1 hour and this data is accessed10 times every second, this means that you mostly have cache hits and everythingis fine. But after 1 hour, we get 10 new requests to a cold cache. So the datais computed again. The next second the same thing happens. So the data is computedabout 50 times before the cache is warm again. This is where you need stampedeprevention

The first solution is to use locking: only allow one PHP process (on a per-host basis)to compute a specific key at a time. Locking is built-in by default, soyou don't need to do anything beyond leveraging the Cache Contracts.

The second solution is also built-in when using the Cache Contracts: instead ofwaiting for the full delay before expiring a value, recompute it ahead of itsexpiration date. The Probabilistic early expiration algorithm randomly fakes acache miss for one user while others are still served the cached value. You cancontrol its behavior with the third optional parameter ofget(),which is a float value called "beta".

By default the beta is 1.0 and higher values mean earlier recompute. Set itto 0 to disable early recompute and set it to INF to force an immediaterecompute:

  1. use Symfony\Contracts\Cache\ItemInterface;
  2.  
  3. $beta = 1.0;
  4. $value = $cache->get('my_cache_key', function (ItemInterface $item) {
  5. $item->expiresAfter(3600);
  6. $item->tag(['tag_0', 'tag_1']);
  7.  
  8. return '...';
  9. }, $beta);

Available Cache Adapters

The following cache adapters are available:

Generic Caching (PSR-6)

To use the generic PSR-6 Caching abilities, you'll need to learn its keyconcepts:

  • Item
  • A single unit of information stored as a key/value pair, where the key isthe unique identifier of the information and the value is its contents;see the Cache Items article for more details.
  • Pool
  • A logical repository of cache items. All cache operations (saving items,looking for items, etc.) are performed through the pool. Applications candefine as many pools as needed.
  • Adapter
  • It implements the actual caching mechanism to store the information in thefilesystem, in a database, etc. The component provides several ready to useadapters for common caching backends (Redis, APCu, Doctrine, PDO, etc.)

Basic Usage (PSR-6)

This part of the component is an implementation of PSR-6, which means that itsbasic API is the same as defined in the document. Before starting to cache information,create the cache pool using any of the built-in adapters. For example, to createa filesystem-based cache, instantiate FilesystemAdapter:

  1. use Symfony\Component\Cache\Adapter\FilesystemAdapter;
  2.  
  3. $cache = new FilesystemAdapter();

Now you can create, retrieve, update and delete items using this cache pool:

  1. // create a new item by trying to get it from the cache
  2. $productsCount = $cache->getItem('stats.products_count');
  3.  
  4. // assign a value to the item and save it
  5. $productsCount->set(4711);
  6. $cache->save($productsCount);
  7.  
  8. // retrieve the cache item
  9. $productsCount = $cache->getItem('stats.products_count');
  10. if (!$productsCount->isHit()) {
  11. // ... item does not exist in the cache
  12. }
  13. // retrieve the value stored by the item
  14. $total = $productsCount->get();
  15.  
  16. // remove the cache item
  17. $cache->deleteItem('stats.products_count');

For a list of all of the supported adapters, see Cache Pools and Supported Adapters.

Advanced Usage