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

tbbc/cache-bundle

TbbcCacheBundle integrates a configurable caching layer into Symfony applications, exposing cache services and helpers for storing, retrieving, and invalidating data across common cache backends. It simplifies cache setup and reuse in Symfony projects.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install the bundle and the annotation reader. The package is not a standalone cache — it wraps whatever backend you configure, so you almost always need doctrine/annotations alongside it:

    composer require tbbc/cache-bundle doctrine/annotations
    
  2. Register the bundle in app/AppKernel.php (Symfony 2/3) or config/bundles.php (if your version allows it):

    new Tbbc\CacheBundle\TbbcCacheBundle(),
    
  3. Configure the storage location. The bundle’s extension is small — open DependencyInjection/Configuration.php in vendor/tbbc/cache-bundle to see the exact tree for your version. A typical minimal config is:

    tbbc_cache:
        cache_dir: '%kernel.cache_dir%/tbbc_cache'
    
  4. Where to look first. In vendor/tbbc/cache-bundle:

    • Annotations/ — the @Cacheable / @CacheRemove annotations and their supported options (key, expires, condition, etc.).
    • Cache/Manager/ — the CacheManager service (usually tbbc_cache.manager) exposing the get/set/remove/has primitives.
    • DependencyInjection/ — the service ids and configuration keys you’ll need to override.
  5. First use case — cache a slow controller action. Annotate the action with @Cacheable. The first request populates the cache; subsequent requests are served from it:

    use Tbbc\CacheBundle\Annotations\Cacheable;
    
    /**
     * @Cacheable(key="homepage_featured", expires=3600)
     */
    public function featuredAction()
    {
        return $this->render('home/featured.html.twig', [
            'items' => $this->productRepo->findFeatured(),
        ]);
    }
    

    Then hit the page twice and confirm an entry appears under var/cache/.../tbbc_cache. If it doesn’t, your annotations aren’t being read (see Gotchas).

Implementation Patterns

Controller response caching (the headline feature). Use @Cacheable on read-heavy actions where the output is identical for all users. Keys should be human-readable constants (homepage_featured) rather than derived values, so you can invalidate them deterministically elsewhere.

Invalidation with @CacheRemove. Pair every cached read with a write path that clears it. This is the pattern the bundle is built around — the annotation layer is essentially a thin, declarative front for CacheManager::remove():

use Tbbc\CacheBundle\Annotations\CacheRemove;

/**
 * @CacheRemove(keys={"homepage_featured"})
 */
public function editFeaturedAction(Request $request)
{
    // ... persist changes ...
    return $this->redirectToRoute('admin_featured');
}

Prefer removing by explicit key over wildcard/namespace clears — wildcard semantics are backend-dependent and easy to get wrong.

Direct CacheManager usage in services. The annotations only fire on the components the bundle instruments. For anything else — a repository method, a mailer lookup, an API client — inject the manager and do it explicitly. This is where the bundle earns its "abstraction" label: you get get/set/remove/has without coupling to a specific backend.

class CurrencyService
{
    private $cache;

    public function __construct($cacheManager) // tbbc_cache.manager
    {
        $this->cache = $cacheManager;
    }

    public function rateFor($code)
    {
        $key = 'fx_rate_' . $code;
        if ($this->cache->has($key)) {
            return $this->cache->get($key);
        }
        $rate = $this->fetchFromProvider($code);
        $this->cache->set($key, $rate, 900);
        return $rate;
    }
}

Key naming conventions. Treat cache keys as a mini schema: {domain}_{entity}_{id} or {domain}:list:{filterHash}. Bake the TTL into the key only when it changes semantics. This makes @CacheRemove(keys={"..."}) calls auditable in code review.

Conditional caching. For actions that differ per user, either fold the identity into the key (cart_$userId) or guard the annotation with a condition so anonymous and logged-in responses share the cache only when safe. Never cache a response containing CSRF tokens or session-flashed data.

Wiring into non-controller code via the event layer. If your bundle version exposes a kernel event listener / interceptor, you can lean on that instead of a controller decorator — this is the natural seam if you need to cache API responses generated by a kernel.view or kernel.response subscriber.

Testing. Because the manager is a service, swap it with an in-memory stub in config_test.yml (alias tbbc_cache.manager to a fake implementing the same CacheManagerInterface). This keeps functional tests hermetic and lets you assert has()/get() calls without touching disk.

Gotchas and Tips

It’s an old, low-traffic bundle (36 stars, 0 dependents). Expect Symfony 2.x/3.x-era constraints, no PSR-6 or PSR-16 interface, and no #[Attribute] support. Before adopting for a new project, weigh it against Symfony’s native cache contracts (Symfony\Contracts\Cache\CacheInterface::get() with a callable), which cover 90% of the same ground with first-class maintenance and PSR compliance. Use this bundle if you have an existing codebase on its supported Symfony line and want the annotation ergonomics.

Annotations must be imported and enabled. A common silent failure: forgetting use Tbbc\CacheBundle\Annotations\Cacheable; in the controller — the annotation is then an unresolved docblock comment and caching is quietly skipped. Equally common: doctrine/annotations missing, or the annotation reader not registered as a service. If nothing is cached, check the reader wiring before blaming the backend.

cache_dir must be writable and included in deploys. The directory (often %kernel.cache_dir%/tbbc_cache) must exist and be writable by the web user. On multi-server deploys it’s local-disk, so a cache written on one node isn’t visible to the others — a real bug on autoscaled infrastructure. Use a shared backend or accept per-node cold starts.

cache:clear and --no-warmup interactions. The bundle’s storage typically lives under the kernel cache dir, so cache:clear wipes it. That’s fine for correctness but means deploy-time warmup of expensive pages has to be done explicitly (a console command calling the manager), not as a side effect of the app cache warmup.

Serialization limits. Whatever you cache is serialized. Closures, resources, and some entities with proxy/collection references won’t round-trip cleanly. Cache scalars, arrays of scalars, or plain DTOs — not Doctrine entities with lazy associations, and not the container itself.

Key collisions are silent. Two actions using key="list" will overwrite each other with no warning. Adopt a namespacing convention from day one (admin_list_products vs api_list_products) and grep for key= during review.

TTL is a ceiling, not a guarantee. The expires value depends on the underlying backend; some managers treat it as a GC hint rather than a hard expiry. If your correctness depends on “must not serve data older than N minutes,” verify the backend honors it. Also note there’s no stampede protection — a popular key expiring under load causes a thundering herd. Stagger TTLs or add a short lock around the producer.

Invalidation is your responsibility. The annotations don’t know about your data model. Any code path that mutates cached data — including direct DB writes, queue workers, and admin commands — must call @CacheRemove or the manager’s remove(). When in doubt, prefer short TTLs over elaborate invalidation graphs.

Extension points worth knowing.

  • Decorate or alias tbbc_cache.manager to add logging, metrics, or a two-level (in-process + distributed) strategy without touching call sites.
  • Override the annotation classes only if you’re comfortable re-implementing the annotation reader wiring — subclassing is safer than replacing.
  • If you need per-request memoization in front of the persistent cache, wrap the manager rather than editing controllers.

Debugging checklist. (1) Is the reader service registered and the annotation imported? (2) Is cache_dir writable and actually populated? (3) Is the key what you think it is — log it in a decorator. (4) Is the backend honoring the TTL? (5) Are you looking at a stale local-dev cache from before a config change — clear it. A 30-second decorator around the manager that logs get/set/remove with key and hit/miss will save you hours.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource