jeroenvdheuve/twig-cache-key-bundle
A Symfony bundle that adds Twig cache-key support, helping applications generate stable, context-aware keys for template and fragment caching so cache reuse and invalidation are more predictable.
This bundle is a Symfony 2/3-era bundle (last tagged release March 2016, now archived). Its job is narrow: make the cache key that Twig derives for a template relative to the project instead of an absolute filesystem path, so that a compiled/warmed Twig cache stays valid when the app lives at a different absolute path (Capistrano releases/… + current symlink, multiple app servers with different mount points, Docker build vs. runtime paths). Keep that scope in mind — it does not add template tags, fragment caching, or HTTP cache behavior.
Minimal steps:
composer.json for the PHP/Symfony/Twig constraints before requiring. On Symfony 4+ / Twig 2+ expect conflicts; you will likely need --ignore-platform-reqs hacks that then fail at boot.composer require jeroenvdheuve/twig-cache-key-bundle:^1.0app/AppKernel.php (namespace is derived from the autoload.psr-4 block — read that first): new JeroenVDHeuvel\TwigCacheKeyBundle\TwigCacheKeyBundle(),DependencyInjection/ and Resources/config/ immediately. The whole package is almost certainly a compiler pass or a service definition that decorates/replaces twig.loader to override getCacheKey(). There is no meaningful config to publish.app/console debug:container twig.loader --show-private, then cache:clear && cache:warmup and compare filenames in app/cache/dev/twig before and after install. They should be stable when you copy the project to a different absolute path.First use case to validate with: a CI-built Twig cache artifact. Build in /build, warmup there, ship var/cache/prod/twig to /var/www/current, and confirm no recompilation happens on first request (watch file mtimes in the Twig cache dir).
No template-level changes. If the bundle works, your {% extends %} / {% include %} code and controller code are unchanged; the effect is entirely in Twig_Environment::getTemplateClass() / loader getCacheKey().
Stability assertion in a test. The only reliable way to know the bundle is doing its job:
$loader = $container->get('twig.loader');
$key1 = $loader->getCacheKey('@App/Default/index.html.twig');
// simulate a different deploy root
chdir($otherRoot); // or copy/symlink the project elsewhere
$key2 = $container->get('twig.loader')->getCacheKey('@App/Default/index.html.twig');
$this->assertSame($key1, $key2);
Run the same assertion with a symlinked current directory pointing at a release dir — that is the real-world shape.
Deploy pipeline integration. Warmup after code sync, before switching the symlink:
bin/console cache:clear --env=prod --no-debug
bin/console cache:warmup --env=prod --no-debug
If keys are relative, the warmed cache survives the symlink flip and is reusable across servers. Measure: count files and mtimes in var/cache/prod/twig after the switch — if they all change, the bundle isn't doing what you think.
Shared/NFS cache dir. Because keys no longer embed the absolute path, you can point twig.cache at a shared volume across app servers. Only do this after the assertion above passes on every node, and confirm the Symfony %kernel.cache_dir% is genuinely identical in structure.
Fallback pattern (recommended). Since the package is archived and tiny, the honest replacement is a ~15-line decorator on twig.loader that returns str_replace($projectDir, '', $absolutePath) (or a hash of the relative path) from getCacheKey(). Treat the bundle as reference source, not a dependency.
Extension point. Don't fork. Decorate twig.loader in services.yml so you keep the native loader's resource tracking and error messages, and keep the stability test in your suite so a future Twig upgrade doesn't silently regress.
Twig_Environment, split loaders (twig.loader.native_filesystem), and Symfony 4+ autowiring/container changes make 2016-era compiler passes fail at boot. Budget for vendoring, not for upstream fixes.index.html.twig). Confirm the key retains the @Bundle namespace; if it doesn't, that's a cache-poisoning bug, not a nicety.realpath() and symlinks. The usual reason absolute paths leak in is FilesystemLoader::getCacheKey() calling realpath(). Verify which side wins: if the bundle resolves through realpath, you get the release directory path and defeat the entire purpose. Test specifically with a symlinked current.cache:clear in the pipeline and key any content-level invalidation off template mtimes or a build version.debug:container twig.loader --show-private to see what's actually registered; a one-off php -r booting the kernel and printing getCacheKey() for one template tells you more than reading the pass; bin/console debug:twig lists loaders and paths in Symfony 2.8+.HttpCache or {% cache %} key problems — different layers, different bugs.How can I help you explore Laravel packages today?