Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Http Cache Bundle Laravel Package

friendsofsymfony/http-cache-bundle

Symfony bundle to enhance HTTP caching: configure cache headers by path/controller, tag responses and invalidate by tags, set up invalidation schemes without code, send purge/ban requests efficiently, vary cache by user type, and plug in custom cache clients.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Install the Package**
   ```bash
   composer require friendsofsymfony/http-cache-bundle

Enable in config/bundles.php:

return [
    // ...
    FriendsOfSymfony\HttpCacheBundle\FOSHttpCacheBundle::class => ['all' => true],
];
  1. Configure Basic Caching Edit config/packages/fos_http_cache.yaml:

    fos_http_cache:
        cache_manager: cache.app
        cache_warmer: fos_http_cache.cache_warmer
        default_ttl: 3600
        default_max_age: 3600
        debug: '%kernel.debug%'
        generate_url_type: 'absolute'  # or 'relative' (now works with proxy_client.varnish.http.base_url)
        cache_control:
            rules:
                - { path: '^/api/', max_age: 3600, shared_max_age: 3600 }
                - { path: '^/public/', max_age: 86400, shared_max_age: 86400 }
    
  2. First Use Case: Cache API Responses Annotate a controller method with @Cache:

    use Symfony\Component\HttpKernel\Attribute\Cache;
    
    #[Cache(maxAge: 600, public: true)]
    public function getData(Request $request): Response
    {
        return new Response('Cached data');
    }
    

Implementation Patterns

Path-Based Caching Rules

Define granular cache rules in fos_http_cache.yaml:

fos_http_cache:
    cache_control:
        rules:
            # Cache all static assets for 1 year
            - { path: '^/assets/', max_age: 31536000, shared_max_age: 31536000 }

            # Cache authenticated user data for 1 hour
            - { path: '^/user/', max_age: 3600, shared_max_age: 3600, roles: ROLE_USER }

            # Dynamic content (no caching)
            - { path: '^/dashboard/', match_response: false }

Tag-Based Invalidation

  1. Tag Responses

    use FriendsOfSymfony\HttpCacheBundle\Tag\TaggableResponseInterface;
    
    public function listPosts(): Response
    {
        $response = new Response($postsJson);
        $response->setSharedMaxAge(3600);
        $response->headers->addCacheControlDirective('public');
    
        // Tag the response for invalidation
        $response = $this->tagResponse($response, ['posts']);
        return $response;
    }
    
  2. Invalidate Tags

    use FriendsOfSymfony\HttpCacheBundle\Invalidation\InvalidationManagerInterface;
    
    public function deletePost(Post $post, InvalidationManagerInterface $invalidationManager): Response
    {
        $entityManager->remove($post);
        $entityManager->flush();
    
        // Invalidate cache tags
        $invalidationManager->invalidateTags(['posts']);
    
        return $this->redirectToRoute('home');
    }
    

Proxy Client Integration

Configure a proxy client (e.g., Varnish) with base_url support:

fos_http_cache:
    proxy_client:
        varnish:
            http:
                base_url: 'http://varnish.example.com'  # Now works with generate_url_type
            dsn: 'http://varnish:6082'
            servers:
                - 'varnish1.example.com'
                - 'varnish2.example.com'

Role-Based Caching

Differentiate cache behavior by user roles:

fos_http_cache:
    cache_control:
        rules:
            - { path: '^/admin/', max_age: 3600, roles: ROLE_ADMIN }
            - { path: '^/user/', max_age: 3600, roles: ROLE_USER }
            - { path: '^/public/', max_age: 86400, shared_max_age: 86400 }

Custom HTTP Cache Client

Extend the default proxy client for custom logic:

use FriendsOfSymfony\HttpCacheBundle\Client\ProxyClientInterface;
use FriendsOfSymfony\HttpCacheBundle\Client\VarnishClient;

class CustomVarnishClient implements ProxyClientInterface
{
    public function purge(string $url, array $tags = []): void
    {
        // Custom purge logic (e.g., with retries or logging)
        $varnishClient = new VarnishClient([
            'dsn' => 'http://varnish:6082',
            'http' => ['base_url' => 'http://varnish.example.com']
        ]);
        $varnishClient->purge($url, $tags);
    }
}

Register the service in config/services.yaml:

services:
    FriendsOfSymfony\HttpCacheBundle\Client\ProxyClientInterface: '@custom.varnish_client'
    custom.varnish_client:
        class: App\Service\CustomVarnishClient

Gotchas and Tips

Common Pitfalls

  1. Expression Language Dependency If using match_response with expressions, ensure symfony/expression-language is installed:

    composer require symfony/expression-language
    
  2. Tag Header Parsing in Symfony HttpCache If using Symfony’s built-in HttpCache, configure the PurgeTagsListener to handle custom tag headers:

    fos_http_cache:
        purge_tags_listener:
            tag_header_parser: 'App\Service\CustomTagHeaderParser'
    
  3. Flash Message Loss on Redirects The bundle fixes flash message loss in redirects (since v2.9.1), but ensure your firewall and session configuration is correct.

  4. Deprecated Configurations

    • cache_manager.generate_url_type is now fully supported with proxy_client.varnish.http.base_url (previously required proxy_client.[client].base_url).
    • Annotations are no longer supported (use attributes in Symfony 5+).
  5. Lazy-Loaded Proxy Clients Clients like fastly and cloudflare are lazy-loaded to support runtime secrets (e.g., API keys). Avoid eager-loading them in tests.

Debugging Tips

  1. Enable Debug Mode Set debug: true in fos_http_cache.yaml to log cache headers and invalidation requests.

  2. Check Cache Headers Inspect HTTP responses with tools like Browser DevTools or cURL:

    curl -I http://your-app.com/api/data
    

    Look for headers like:

    Cache-Control: public, max_age=3600
    X-Proxy-Cache: HIT
    
  3. Validate Invalidation Use the fos:httpcache:clear command to test full cache invalidation:

    php bin/console fos:httpcache:clear
    
  4. Log Invalidation Requests Enable logging for the InvalidationListener:

    services:
        FriendsOfSymfony\HttpCacheBundle\EventListener\InvalidationListener:
            calls:
                - [setLogger, ['@logger']]
    

Performance Optimization

  1. Avoid Over-Tagging Tag responses sparingly to minimize invalidation overhead. Use broad tags (e.g., products) instead of granular ones (e.g., product_123).

  2. Use shared_max_age for Public Content Set shared_max_age for content that can be cached by CDNs or shared proxies:

    - { path: '^/blog/', max_age: 300, shared_max_age: 86400 }
    
  3. Leverage reverse_proxy_ttl Configure a custom TTL header for reverse proxies:

    fos_http_cache:
        cache_control:
            reverse_proxy_ttl: 3600
            ttl_header: 'X-Cache-TTL'
    
  4. Disable Caching for Dynamic Routes Use match_response: false for routes with dynamic content:

    - { path: '^/search/', match_response: false }
    

Extension Points

  1. Custom Response Matcher Extend the ResponseMatcher to implement complex logic:

    use FriendsOfSymfony\HttpCacheBundle\Matcher\ResponseMatcherInterface;
    
    class CustomResponseMatcher implements ResponseMatcherInterface
    {
        public function match(Request $request, Response $response): bool
        {
            // Custom logic (e.g., check response body for dynamic content)
            return strpos($response->getContent(), 'dynamic') === false;
        }
    }
    

    Register it in fos_http_cache.yaml:

    fos_http_cache:
        response_matcher: 'App\Matcher\CustomResponseMatcher'
    
  2. Event Listeners Subscribe to cache events (e.g., fos_http_cache.invalidate_tags):

    use Symfony\Component\EventDispatcher\Attribute\AsEvent
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
escalated-dev/escalated-laravel
escalated-dev/locale
vusys/laravel-runabout
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
directorytree/opensearch-client
directorytree/opensearch-adapter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php