Weave 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 Extra Bundle Laravel Package

m6web/cache-extra-bundle

Symfony bundle that integrates m6web/cache-extra, adding tag-based cache invalidation and namespace support on top of PSR-6/Symfony cache pools. Useful when you need to clear groups of entries without flushing the whole backend; wired via bundle DI configuration.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this bundle is archived (last release 2016-02-11, zero stars, zero dependents). It targets the Symfony 2.x/3.x era, doctrine/annotations, and m6web/cache-bundle as its cache backend. Before you invest time, confirm your project can actually install it — on Symfony 4+ / PHP 7.2+ you will almost certainly hit constraint or API incompatibilities, and the annotation listener relies on the old Controller event flow. Treat it as a reference implementation unless you are maintaining a legacy app that already uses it.

Assuming a compatible legacy stack:

  1. Install and register

    composer require m6web/cache-extra-bundle
    
    // app/AppKernel.php
    new M6Web\Bundle\CacheExtraBundle\M6WebCacheExtraBundle(),
    

    It depends on m6web/cache-bundle (or an equivalent PSR-6-ish cache service) being configured, since CacheExtraBundle is a thin annotation layer over a cache provider — it does not ship its own storage.

  2. Wire the cache service

    # config.yml
    m6_web_cache_extra:
        cache_service: m6_web_cache   # the service id of your configured provider
    

    Verify the exact key name against the bundle's DependencyInjection/Configuration.php — the config surface is small but the option names matter.

  3. Where to look first

    • Annotation/Cache.php and Annotation/CacheInvalidate.php — these define the actual annotation surface (expiry/TTL, keys, etc.).
    • Listener/CacheAnnotationListener.php and Listener/CacheInvalidateAnnotationListener.php — this is where the real behavior lives: key derivation, read/write on the controller event, and invalidation on the response.
    • The README's two short examples are the whole documented API; the listeners are the source of truth.
  4. First use case — cache a hot, read-only controller action:

    use M6Web\Bundle\CacheExtraBundle\Annotation\Cache;
    
    /**
     * @Cache(expires=60)
     */
    public function listAction()
    {
        // expensive query
    }
    

    Hit the endpoint twice and confirm the second request short-circuits (add a log line or var_dump in the action to verify it is not executed).

Implementation Patterns

Read caching on controller actions. The primary pattern is annotating actions that are expensive and side-effect free. TTL-based expiry is the default lever; the bundle derives a cache key from the request (route + parameters, typically), so identical requests share an entry. Keep cached actions free of session-dependent, user-specific, or Vary-sensitive output unless you are certain the key accounts for it.

Explicit invalidation on writes. Pair every cached read with a @CacheInvalidate annotation on the action that mutates the underlying data:

use M6Web\Bundle\CacheExtraBundle\Annotation\CacheInvalidate;

/**
 * @CacheInvalidate(keys={"article_list", "article_42"})
 */
public function updateAction($id) { ... }

The invalidation listener runs on the controller event and removes the named keys before/around the action, so the next read repopulates. This is the bundle's real value: annotation-driven invalidation without hand-writing $cache->delete() calls scattered through controllers.

Design a key namespace up front. Because keys are strings you control via the annotations, adopt a convention ({resource}_{id}, {route}_{hash(params)}) and centralize the list of invalidated keys. This is the single biggest determinant of whether the bundle helps or hurts — ad-hoc keys lead to stale pages that are painful to trace.

Integrate at the provider level. Set cache_service to the same provider used elsewhere (m6web/redis-bundle, an APC provider, etc.) so cache clears, monitoring, and eviction policies apply uniformly. If you also use HTTP caching (HttpCache, FOSHttpCache), decide whether this bundle is the application-layer cache behind your HTTP cache, or whether you should drop it in favor of Cache-Control/ESI — running both without a clear layering story produces confusing stale data.

Testing. The listeners are the seam. In functional tests, either disable the listener for the test environment (so actions always execute) or use an in-memory cache provider and assert on hit/miss behavior explicitly. Unit-test key generation logic by invoking the listener with a mocked request rather than through the kernel.

Gotchas and Tips

  • It is abandoned. No security patches, no Symfony 4+/PHP 7.x compatibility guarantees, and zero dependents means no community fixes. If you are starting fresh, prefer Symfony's symfony/cache contracts with a small custom subscriber, or FOSHttpCacheBundle/friendsofsymfony/http-cache for HTTP-layer caching. The 10 lines of annotation parsing you'd save are not worth an unmaintained dependency.
  • Annotation parsing requires doctrine/annotations and the annotations must be in docblocks the reader scans — annotations on inherited or trait methods, or in files not autoloaded the way the reader expects, silently do nothing. If caching "doesn't work," verify the listener is registered and the annotation is actually being read before debugging the cache itself.
  • Silent no-ops are the default failure mode. A misconfigured cache_service or a typo in the annotation name typically produces no error — just no caching. Add a temporary log in the listener to confirm it fires.
  • Invalidation is manual and string-based. Nothing ties cache keys to your entities; rename a key in one annotation and forget the matching @CacheInvalidate, and you get permanent stale entries. Keep the key list in one place or generate it from a helper.
  • Request-derived keys may not include what you expect. Headers, cookies, and Vary dimensions are generally not part of the key. User-specific content (auth state, locale via cookie, A/B buckets) will be cross-served. Bake those into the key or exclude the action from caching.
  • Cache stampede on expiry. With TTL-only expiry and no locking, a cold key under load sends every concurrent request to the origin. For hot endpoints, consider a longer TTL plus explicit invalidation instead of short TTLs.
  • Debugging shortcuts: check the provider directly (e.g. redis-cli KEYS 'prefix*'), temporarily set expires very low, and disable the listener in config_test.yml to isolate whether an issue is caching or application logic.
  • Extension points are limited — the listeners are not designed for heavy customization beyond swapping the cache provider. If you need per-user keys, tag-based invalidation, or stampede protection, you are better off building a small event subscriber on kernel.controller / kernel.response yourself than patching this bundle.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package