1

I'm using the twig cache in a Symfony 5.4 project. If I cache something like:

{% cache "customer_1" ttl(3600) tags('customer') %}
Some HTML here
{% endcache %}

I need to be able to invalidate the twig cache with tag customer from within a Symfony controller or service.

I've tried autoloading Symfony\Contracts\Cache\TagAwareCacheInterface $twigCache (found from bin/console debug:autowiring) but this doesn't seem to work.

With this I called $twigCache->invalidateTags(['customer']), but does not appear to do nothing.

Is it possible to access and clear the twig cache from the Symfony side?

yivi
  • 42,438
  • 18
  • 116
  • 138
fistameeny
  • 1,048
  • 2
  • 14
  • 27

2 Answers2

2

Apparently, you are doing it correctly.

I have just set up a Symfony 5.4 project from scratch and tried it, and it works as expected.

E.g.:

composer create-project symfony/skeleton:"5.4.*" twig-cache-5.4
cd twig-cache-5.4
composer req twig
composer req twig/cache-extra
<?php declare(strict_types=1);

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Cache\TagAwareCacheInterface;
use Twig\Environment;

#[AsController]
#[Route('/super-cache/{tag}', 'super')]
readonly class SuperController
{

    public function __construct(
        private Environment            $twig,
        private TagAwareCacheInterface $twigCache,
    )
    { }

    public function __invoke(?string $tag = null): Response
    {

        if ($tag !== null) {
            $this->twigCache->invalidateTags([$tag]);
        }

        return new Response($this->twig->render('super.html.twig'));
    }
}

And the template:

{% extends 'base.html.twig' %}

{% block body %}

<H1>Hello, content</H1>

{% cache "first-key" tags('foo') %}
    <p>Key "main-key", tag "foo" (cached at: {{ "now"|date("F jS \\a\\t g:ia") }})</p>
{% endcache %}


{% cache "second-key" tags('foo') %}
    <p>Key "second-key", tag "foo" (cached at: {{ "now"|date("F jS \\a\\t g:ia") }})</p>
{% endcache %}

{% cache "third-key" tags('bar') %}
    <p>Key "third-key", tag "bar" (cached at: {{ "now"|date("F jS \\a\\t g:ia") }})</p>
{% endcache %}

<p>This is some uncached content.</p>

{% endblock %}

I have verified with bin/console cache:pool:list that the pool twig.cache has been created, so I can autowire that pool directly with $twigCache.

If I access /super-cache, the first time the template will be cached completely, and the "cached at" string won't change in following calls:

Execution result

Now accessing /super-cache/foo, the controller will invalidate the tag foo for the pool, and the template content will be refreshed accordingly (check the "created at" string on the first two blocks):

Show results with cache invalidated

Knowing that this should work as intended, you'll need to find if there is something else amiss in your setup.

yivi
  • 42,438
  • 18
  • 116
  • 138
  • Thanks for taking the time to rig up an example. I'll re-check my app config to make sure I've not missed a step – fistameeny Jul 25 '23 at 12:06
-2

to clear indivduel tags you can use:

bin/console cache:pool:invalidate-tags

this uses the exact same command ($pool->invalidateTags($tags)) you tried to use. so it should work. see vendor/symfony/framework-bundle/Command/CachePoolInvalidateTagsCommand.php

Rufinus
  • 29,200
  • 6
  • 68
  • 84