Symfony-docs: Documentation for the new PSR-6 Cache component

Created on 20 Jan 2016  路  23Comments  路  Source: symfony/symfony-docs

  • [x] symfony/symfony#17408 (the component)
  • [ ] symfony/symfony#18667 (integration into the FrameworkBundle)
Cache FrameworkBundle

All 23 comments

I love the energy and passion that the Symfony community is showing around the new Cache component. I'd like to start documenting it and adding it to symfony.com list of components.


But before that, I'd like to share with you how I'd like this new cache to work in Symfony. I'd like to have a "global" and standard way of using a cache for services and bundles. Similar to the way we use Monolog today for logging anything.

So, my question: is the following explanation how the Cache would work in Symfony?


Defining application caches

When defining one cache, Symfony names it default automatically (same behavior as "swiftmailer" mailers and "doctrine" managers)

# app/config/config.yml

# simple cache without arguments
cache:
    type: array

# equivalent to:
# cache:
#    default:
#        type: array

Complex caches can define arguments:

# app/config/config.yml
cache:
    type: doctrine
    em: my_custom_em_id

You can also define lots of different caches in a single app:

# app/config/config.yml
cache:
    default:
        type: array
    db:
        type: doctrine
        em: my_custom_em_id

They are available in the application as cache.default and cache.db services.
The cache service is an alias for cache.default.

Configuring the application caches

Params such as default_lifetime and namespace are available for any cache type:

# app/config/config.yml
cache:
    type: array
    default_lifetime: 600
    namespace: 'ACME__'

Using caches in Symfony components

All Symfony components define a cache option. Its value can be:

1) A boolean, to enable or disable the cache. If true, the default cache is used:

# app/config/config.yml
framework:
    validation:
        cache: true
        enable_annotations: true
    serializer:
        cache: true
    property_path:
        cache: true

doctrine:
    orm:
        cache: true
# you can also set 'metadata_cache_driver', 'result_cache_driver' 
# and 'query_cache_driver' separately

You can also set the id of the cache and even an array of cache ids for complex services:

# app/config/config.yml
framework:
    validation:
        cache: db
        enable_annotations: true
    serializer:
        cache: default
    property_path:
        cache: default

doctrine:
    orm:
        cache: [db, default]

This cache can also be used for third-party bundles:

# app/config/config.yml
liip_imagine:
    cache: true # or false, or 'db', or ['db', 'default'], etc.

What you are mentioning is not Component docs, but bundle docs (cookbook related), @javiereguiluz.

Apart from that, I cannot answer your questions as I haven't looked at caching yet

@javiereguiluz Your ideas sound quite nice to me and I think you should raise this idea in the code repo (we are not there right now, but the work to integrate PSR-6 caches in the different components has started). Some of the things you talk about are out of the scope of the Symfony core as they need to be handled in third-party bundles, but we should of course think about how can make using the new cache component as easy as possible.

For anyone interested: Javier opened symfony/symfony#17537.

Is there any documentation for symfony/symfony#18371 (also symfony/symfony#18544 and symfony/symfony#18561 which introduced default cache pools for the Validator and Serializer)?

@nicolas-grekas @tgalopin

How would the user switch to use ApcuAdapter, for instance? Is it by overriding the adapter for the default cache pools, or by declaring new cache pools?

The recommended (as per config_prod.yml in symfony-standard) validator.mapping.cache.doctrine.apc and serializer.mapping.cache.doctrine.apc are using the old ApcCache which requires the apcu_bc PECL package (apc.so extension) for PHP >= 7. I think that needs to change...

@teohhanhui You are right, these PR should be documented.

However, note that these three PR do not change any behavior when the user enabled APC cache: these PR are simply a fallback to filesystem when the user didn't change the config_prod file.

The recommended cache will also need to change from APC to OPCache as much as possible. That's the aim of the PR https://github.com/symfony/symfony/pull/18533 and there will be other PRs for other components (validator and serializer mainly).

PS : the cache pools system definitely needs some documentation, it's a really powerful system but more complex than what was present before.

This comment could be a good basis for documentation: https://github.com/symfony/symfony/pull/18371#issuecomment-204300288

If so, then shouldn't that be the new recommendation in config_prod.yml?

p/s: OpCacheAdapter or ApcuAdapter, that's a separate issue...

@teohhanhui Your configuration sample is right, but as it's not completely stable yet (some ideas emerged to improve developer experience on various levels), it's not yet documented. But it should be before release, that's true.

I'm trying to write the docs for this component (and its integration with FrameworkBundle). So I'll ask for help to @tgalopin and @nicolas-grekas to see if I understand their work.


In the Symfony Demo app, we have this action to display the blog index:

    public function indexAction($page)
    {
        $posts = $this->get('cache.pool.local')->getItem('blog-posts-latest');

        return $this->render('blog/index.html.twig', array('posts' => $posts));
    }

I'm trying to use a filesystem cache to avoid the database query:

    public function indexAction($page)
    {
        if ($this->get('cache.pool.local')->hasItem('blog-posts-latest')) {
            $posts = $this->get('cache.pool.local')->getItem('blog-posts-latest');
        } else {
            $posts = $this->getDoctrine()->getRepository('AppBundle:Post')->findLatest($page);
            $item = $this->get('cache.pool.local')->getItem('blog-posts-latest');
            $item->set($posts);
            $this->get('cache.pool.local')->save($item);
        }

        return $this->render('blog/index.html.twig', array('posts' => $posts));
    }

The "pools" are created, but no contents are cached. Everything is empty:

cache_pools

Any clue? Thanks!

You should call Psr\Cache\CacheItemInterface::isHit. Also, note that Psr\Cache\CacheItemPoolInterface::getItem returns Psr\Cache\CacheItemInterface, so the following is obviously wrong:

// wrong!
$posts = $this->get('cache.pool.local')->getItem('blog-posts-latest');

It's unsafe to use the - character in cache key as it's not guaranteed to be supported.

Working example: https://github.com/api-platform/core/blob/b655b91f83e2acb4040767dab51452512638e45c/src/Metadata/Property/Factory/CachedPropertyMetadataFactory.php

@teohhanhui I've changed the code like this, but everything is still empty:

    public function indexAction($page)
    {
        $cachedPosts = $this->get('cache.pool.local')->getItem('blog-posts-latest');

        if ($cachedPosts->isHit()) {
            $posts = $cachedPosts->get();
        } else {
            $posts = $this->getDoctrine()->getRepository('AppBundle:Post')->findLatest($page);
            $cachedPosts->set($posts);
            $this->get('cache.pool.local')->save($cachedPosts);
        }

        return $this->render('blog/index.html.twig', array('posts' => $posts));
    }

@teohhanhui OK, the problem was that I was trying to cache a Pagerfanta object and somehow that cannot be cached. Sadly I didn't get any exception or error message or log. If I cache $posts->getIterator(), it works.

@javiereguiluz PSR-6 forbids throwing exceptions for unserializable values. But we could easily add a logger, only a service tag is missing. In which channel would you do that?

What about using cache as the channel?

Need to document symfony/symfony#18667

@teohhanhui yes, but I'll do that in a separate PR. This is only for the component and then we'll document the integration of Cache in the Symfony framework.

@javiereguiluz I am confused, where can I find complete description of cache component configuration in symfony framework? There is nothing about it in symfony docs website.

@Arkemlar sadly that's correct! We don't have yet this doc about using Cache inside the Symfony framework.

Reopening, the framework integration is indeed still missing as stated in the original post.

Closing again as we already track it in https://github.com/symfony/symfony-docs/issues/7006.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

anush picture anush  路  5Comments

x8core picture x8core  路  4Comments

dannyvw picture dannyvw  路  3Comments

steevanb picture steevanb  路  4Comments

Nyholm picture Nyholm  路  4Comments