friendsofsymfony/http-cache
PHP library to integrate apps with HTTP caching proxies (Varnish, NGINX, Symfony HttpCache, Fastly, Cloudflare). Send efficient cache invalidation/purge and tag requests, abstract proxy features, and test caching/invalidation with PHPUnit tools.
Installation:
composer require friendsofsymfony/http-cache
For Symfony projects, prefer the fos/http-cache-bundle for seamless integration.
First Use Case:
use FriendsOfSymfony\HTTPCache\Invalidator\InvalidatorInterface;
use FriendsOfSymfony\HTTPCache\Invalidator\VarnishInvalidator;
$invalidator = new VarnishInvalidator('http://varnish-server:6082');
$invalidator->invalidate('/path/to/resource');
NullInvalidator (no-op):
$invalidator = new NullInvalidator();
Where to Look First:
InvalidatorInterface for supported methods.Invalidation Strategies:
$invalidator->invalidate('/blog/post-1');
$invalidator->invalidateTag('blog_posts');
$invalidator->invalidateRegex('/^\/blog\/post-\d+$/');
Integration with Symfony:
FOSHttpCacheBundle to auto-register the invalidator as a service:
# config/packages/fos_http_cache.yaml
fos_http_cache:
invalidator:
varnish:
host: 'http://varnish:6082'
public function updatePost(Post $post, InvalidatorInterface $invalidator) {
$post->updateTitle('New Title');
$invalidator->invalidate("/blog/{$post->slug}");
}
Testing:
$mockInvalidator = $this->createMock(InvalidatorInterface::class);
$mockInvalidator->expects($this->once())->method('invalidate')->with('/test');
NullInvalidator in local/dev environments to bypass real invalidation.Event-Driven Invalidation:
kernel.terminate) to invalidate cached responses:
public function onKernelTerminate(GetResponseForControllerResultEvent $event) {
$invalidator = $event->getRequest()->get('invalidator');
$invalidator->invalidate($event->getRequest()->getUri());
}
Custom Invalidators:
AbstractInvalidator for non-Varnish proxies (e.g., Nginx):
class NginxInvalidator extends AbstractInvalidator {
public function invalidate($url) {
// Custom Nginx purge logic
}
}
Varnish-Specific Features:
invalidateTag) is Varnish-only. Other proxies (e.g., Nginx) may ignore this.invalidateRegex) may not be supported by all proxies. Test thoroughly.Connection Issues:
$invalidator = new VarnishInvalidator('http://varnish:6082', 5.0); // 5s timeout
try {
$invalidator->invalidate('/path');
} catch (\RuntimeException $e) {
\Log::error("Cache invalidation failed: " . $e->getMessage());
}
Performance:
/blog/* tags at once instead of per-post)./ triggers full cache rebuild).Symfony Cache vs. HTTP Cache:
Cache component. Use both together:
// Invalidate Symfony cache (e.g., Doctrine, OpCache)
$cache->clear();
// Invalidate HTTP cache (Varnish/Nginx)
$invalidator->invalidate('/path');
Enable Logging:
VarnishInvalidator to log requests:
$invalidator = new VarnishInvalidator('http://varnish:6082', null, [
'logger' => new \Monolog\Logger('cache')
]);
varnishlog) for invalidation failures.Validate Proxy Configuration:
curl:
curl -X PURGE http://varnish-server:6082/path/to/resource
PURGE method (or equivalent).Common Errors:
Custom Headers:
$invalidator = new VarnishInvalidator('http://varnish:6082', null, [
'headers' => ['X-Cache-Key' => 'custom_key']
]);
Retry Logic:
$invalidator = new RetryInvalidator(new VarnishInvalidator('http://varnish:6082'), 3);
(Create a decorator class wrapping InvalidatorInterface.)Dynamic Proxy Selection:
dev, staging, prod):
$proxyUrl = config('fos_http_cache.proxy_url');
$invalidator = new VarnishInvalidator($proxyUrl);
Metrics:
$invalidator = new InstrumentedInvalidator(
new VarnishInvalidator('http://varnish:6082'),
new StatsdClient()
);
Symfony Bundle:
fos_http_cache to be loaded after framework in config/bundles.php:
return [
// ...
FriendsOfSymfony\FOSHttpCacheBundle\FOSHttpCacheBundle::class => ['all' => true],
];
# config/packages/fos_http_cache.yaml
fos_http_cache:
invalidator:
varnish:
host: '%env(VARNISH_HOST)%'
NullInvalidator:
# config/packages/fos_http_cache.yaml
fos_http_cache:
invalidator: ~ # Disables NullInvalidator in production
How can I help you explore Laravel packages today?