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

Cache Response Bundle Laravel Package

danilovl/cache-response-bundle

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require danilovl/cache-response-bundle

Ensure Danilovl\CacheResponseBundle\CacheResponseBundle::class is enabled in config/bundles.php.

  1. Basic Configuration: Enable the bundle in config/packages/danilovl_cache_response.yaml:

    danilovl_cache_response:
        enable: true
    
  2. First Use Case: Cache a controller response for 60 seconds using a static key:

    use Danilovl\CacheResponseBundle\Attribute\CacheResponseAttribute;
    
    #[CacheResponseAttribute(key: 'homepage', expiresAfter: 60)]
    public function index(): Response
    {
        return new Response('Cached content');
    }
    

Key Files to Review

  • config/packages/danilovl_cache_response.yaml (Configuration)
  • src/Attribute/CacheResponseAttribute.php (Attribute definition)
  • src/Command/ (CLI commands for cache management)

Implementation Patterns

Common Workflows

1. Dynamic Key Generation

Use __METHOD__ or a combination of route/query parameters for unique keys:

#[CacheResponseAttribute(
    key: __METHOD__,
    useRoute: true,
    useQuery: true,
    expiresAfter: 300
)]
public function show(Product $product): Response
{
    return $this->render('product/show.html.twig', ['product' => $product]);
}

2. Conditional Caching

Disable caching for POST requests or specific queries:

#[CacheResponseAttribute(
    key: 'dashboard',
    expiresAfter: 900,
    disableOnRequest: true, // Skip cache for POST/PUT/PATCH
    disableOnQuery: true   // Skip cache if query params exist
)]
public function dashboard(): Response
{
    return $this->render('dashboard.html.twig');
}

3. Custom Cache Key Factories

Implement CacheKeyFactoryInterface for complex key logic:

class UserSpecificCacheKeyFactory implements CacheKeyFactoryInterface
{
    public function __invoke(Request $request, array $options): string
    {
        return 'user_'.($request->attributes->get('user')?->getId()).'_'.md5($request->getPathInfo());
    }
}

Use it in your controller:

#[CacheResponseAttribute(factory: UserSpecificCacheKeyFactory::class)]
public function profile(): Response
{
    // ...
}

4. Integration with Symfony Events

Clear caches during critical events (e.g., user updates):

use Danilovl\CacheResponseBundle\Event\ClearCacheResponseKeyEvent;

public function onUserUpdated(UserUpdatedEvent $event)
{
    $this->eventDispatcher->dispatch(
        new ClearCacheResponseKeyEvent('user_'.$event->getUser()->getId().'_*')
    );
}

5. Priority-Based Caching

Adjust kernel listener priorities in config:

danilovl_cache_response:
    kernel_controller_priority: -100  # Run before other controllers
    kernel_response_priority: 100     # Run after other responses

Integration Tips

Laravel-Specific Adaptations

  1. Service Provider Setup: Register the bundle in config/app.php under providers:

    Danilovl\CacheResponseBundle\CacheResponseBundle::class,
    
  2. Cache Adapter Configuration: Use Laravel’s cache drivers (e.g., cache.array, cache.redis) by configuring the cache_adapter:

    danilovl_cache_response:
        cache_adapter: 'Symfony\Contracts\Cache\CacheInterface'
    

    Bind the adapter in Laravel’s DI container (e.g., AppServiceProvider):

    $this->app->bind(
        CacheItemPoolInterface::class,
        fn() => Cache::store('array')->getCachePool()
    );
    
  3. Artisan Command Aliases: Create Laravel-friendly aliases for CLI commands in app/Console/Kernel.php:

    protected $commands = [
        Commands\CacheResponseListCommand::class,
        Commands\CacheResponseClearCommand::class,
    ];
    

    Now use:

    php artisan cache:response:list
    php artisan cache:response:clear --cacheKey=homepage
    
  4. Attribute Routing: Combine with Laravel’s route caching:

    #[Route('/cached', name: 'cached_route')]
    #[CacheResponseAttribute(key: 'cached_route', expiresAfter: 3600)]
    public function cachedRoute(): Response
    {
        return response()->json(['data' => 'cached']);
    }
    

Gotchas and Tips

Pitfalls

  1. Key Collisions:

    • Issue: Using useRequest: true with complex requests (e.g., file uploads) may generate overly long keys or collisions.
    • Fix: Prefer useQuery: true or useRoute: true for most use cases. For custom logic, implement CacheKeyFactoryInterface.
  2. Cache Invalidation:

    • Issue: Forgetting to clear caches after data changes (e.g., database updates) leads to stale responses.
    • Fix: Use the ClearCacheResponseKeyEvent or CLI commands (php artisan cache:response:clear) during critical updates.
  3. Priority Conflicts:

    • Issue: Kernel listener priorities may interfere with middleware or other bundles.
    • Fix: Test with kernel_controller_priority and kernel_response_priority set to extreme values (e.g., -1000 or 1000) to isolate issues.
  4. Environment-Specific Caching:

    • Issue: useEnv: true may cause cache keys to differ between environments (e.g., APP_DEBUG).
    • Fix: Avoid useEnv: true unless explicitly needed. Use environment-specific cache prefixes instead.
  5. Session Data Bloat:

    • Issue: useSession: true includes session data in keys, which can grow unbounded.
    • Fix: Limit to essential session variables or use a custom factory to extract specific data.

Debugging

  1. List All Cache Keys:

    php artisan cache:response:list
    
    • Tip: Look for unexpected keys (e.g., overly long or malformed) to debug key generation.
  2. Clear Specific Patterns: Use wildcards to clear related keys:

    php artisan cache:response:clear --cacheKey="user_*"
    
  3. Profiler Integration:

    • The bundle includes Symfony Profiler support. Check the "Cache" tab to inspect cached responses and keys.
    • Tip: Compare "before" and "after" profiles to verify caching is working.
  4. Log Cache Hits/Misses: Enable debug mode and check logs for:

    CacheResponseBundle: Cache hit/miss for key "..." in "..." seconds.
    

Configuration Quirks

  1. Default Cache Adapter:

    • If cache_adapter is not set, the bundle falls back to Symfony’s default CacheItemPoolInterface (e.g., cache.app in Laravel).
    • Tip: Explicitly configure it to avoid surprises:
      danilovl_cache_response:
          cache_adapter: 'Symfony\Contracts\Cache\CacheInterface'
      
  2. Boolean Flags:

    • Flags like disableOnQuery are strictly boolean. Avoid passing strings or integers.
    • Incorrect:
      disableOnQuery: 1  # Won't work!
      
    • Correct:
      disableOnQuery: true
      
  3. ExpiresAfter vs. ExpiresAt:

    • expiresAfter accepts seconds or a DateInterval (e.g., expiresAfter: 'PT1H').
    • expiresAt requires a DateTimeInterface object.
    • Tip: Use expiresAfter for simplicity unless you need precise expiration times.

Extension Points

  1. Custom Cache Tags: Extend the bundle to support cache tags (e.g., CacheTagAwareInterface) for group invalidation:

    #[CacheResponseAttribute(tags: ['products'])]
    public function productList(): Response
    {
        // ...
    }
    
    • Implementation: Subclass CacheResponseAttribute and add tag support to the listener.
  2. Cache Warmup: Pre-populate caches during deployment:

    use Danilovl\CacheResponseBundle\CacheResponseWarmer;
    
    class CacheWarmer implements CompilerPassInterface
    {
        public function process(ContainerBuilder $container)
        {
            $container->addCompilerPass(new CacheResponseWarmer());
        }
    }
    
  3. Vary Headers: Add Vary headers dynamically based on cache keys:

    // In a subscriber or listener
    $response->headers->set('Vary', 'Accept, User-Agent');
    
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.
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui