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

winzou/cache-bundle

A Symfony bundle that provides a simple, unified cache service with support for multiple backends such as APC, Memcache, Redis, and filesystem. It offers an easy-to-use interface for storing and retrieving cached data with configurable lifetimes.

View on GitHub
Deep Wiki
Context7

Getting Started

This bundle is a thin Symfony 2 wrapper around Zend\Cache (ZF2). It does not implement caching itself — it gives you configured Zend\Cache\Storage\StorageInterface instances as services so you don't hand-build adapters in every project. Treat it as a configuration/DI convenience layer, not a framework feature.

Requirements to verify before anything else (read composer.json in the repo, not the README):

  • Symfony 2.x (AppKernel, bundle registration).
  • zendframework/zend-cache ~2.x. The later laminas/laminas-cache rename is not compatible; neither is Symfony 3+ without changes.
  • The backends it advertises (apc, xcache, file, zenddata, array) are mostly legacy: XCache is gone on PHP 7+, the APC adapter targets the old APC extension (not modern APCu), and ZendData requires Zend Server. On a working stack, expect to use file (persistent) and array (per-request/tests).

Install and register:

composer require winzou/cache-bundle
// app/AppKernel.php
public function registerBundles()
{
    $bundles = array(
        // ...
        new Winzou\CacheBundle\WinzouCacheBundle(),
    );
}

Configure one instance per logical cache, not one global cache. The real source of truth for keys is DependencyInjection/Configuration.php; open it first — the README lags the code.

# app/config/config.yml
winzou_cache:
    instances:
        app_data:
            type: file
            options:
                cache_dir: %kernel.cache_dir%/winzou/app_data
                namespace: myapp_data
                ttl: 3600

First use case — cache an expensive repository call:

$cache = $this->get('winzou_cache')->get('app_data');
// Depending on the version, instances may also be exposed directly as
// 'winzou_cache.app_data' — check Resources/config/services.xml.

$key = 'user.'.$id.'.profile';

if (null === ($profile = $cache->getItem($key, $success)) || !$success) {
    $profile = $profileRepository->loadProfile($id);
    $cache->setItem($key, $profile);
}

If winzou_cache does not expose get() in your version, inject winzou_cache.app_data directly.

Implementation Patterns

Inject the manager, resolve names once. In a service, take the cache manager (or the concrete instance service) as a constructor argument and fetch the named instance in the constructor. Avoid $container->get() inside domain code — the bundle's service ids become a framework detail you can't later swap.

Wrap it in your own typed cache. Never let setItem/getItem calls spread across the codebase. One small class per domain area gives you typed methods and a single place to migrate to symfony/cache later:

class ProfileCache
{
    private $cache;

    public function __construct(\Zend\Cache\Storage\StorageInterface $cache)
    {
        $this->cache = $cache;
    }

    public function get($id, callable $fallback)
    {
        $key = 'v3.user.'.$id.'.profile';

        if (null !== ($value = $this->cache->getItem($key, $success)) && $success) {
            return $value;
        }

        $value = $fallback();
        $this->cache->setItem($key, $value);

        return $value;
    }

    public function invalidate($id)
    {
        $this->cache->removeItem('v3.user.'.$id.'.profile');
    }
}

The callable $fallback cache-aside signature is the single most valuable pattern here — it removes the repeated get/miss/set boilerplate that causes most caching bugs.

Version your keys, don't flush. Prefix keys with v1., v2., etc. A schema change means bumping the prefix in one constant; old entries expire naturally. This is much safer than calling flush(), especially on shared backends.

Namespace every instance. Set an explicit namespace option per instance. Two apps or two instances sharing the same APC/memcached/file backend will otherwise collide under Zend's default namespace.

Use the array adapter for tests. Override the instance's type to array in config_test.yml. It is in-process only, so it gives you deterministic behavior without clearing real caches between tests.

Separate data caches from Symfony's caches deliberately. If cache_dir lives under %kernel.cache_dir%, cache:clear wipes your data along with Symfony's. That's often desirable in dev; in production put it elsewhere and add an explicit clear step to your deploy. Either way, decide on purpose.

Warm hot keys at deploy time. A small console command that calls your ProfileCache::get() for the top N ids (or triggers your normal code path) turns cold-cache latency into a deploy cost. Run it after the clear step.

Invalidate on write, not on a timer. In the repository/service that updates the entity, call invalidate($id). TTLs are a backstop, not an invalidation strategy, unless stale reads are acceptable for that data.

Fallback for unsupported backends. If you need Redis or Memcached and the bundle doesn't expose it, don't patch the bundle. Define your own Zend\Cache\Storage\StorageInterface service in your app's DI and inject it into your wrapper — the wrapper is the contract, not the bundle.

Gotchas and Tips

  • A cache miss and a cached null look identical. getItem() returns null on miss; use the &$success by-reference parameter (or hasItem()) if you ever cache nulls or falsy values. This is the most common silent bug with Zend\Cache.
  • Default key pattern is restrictive. Zend's adapters validate keys against a key_pattern and throw on illegal characters. Separators like : may be rejected — use . or _, or relax key_pattern in the options. This bites everyone once.
  • Key length limits are real. APC and file paths both have limits; hash long or user-derived keys (md5($raw)) rather than storing raw composite strings.
  • ttl: 0 means "never expires" in Zend\Cache. Omitting TTL entirely on a file/APC instance means stale entries accumulate forever. Always set a TTL or an explicit invalidation path.
  • Per-item TTL is not in the base setItem($key, $value) signature. TTL is typically configured at the adapter/instance level (ttl option or getOptions()->setTtl()). Verify support for your zend-cache version before assuming a per-call TTL works — silently falling back to the instance default is the failure mode.
  • flush() on a shared backend can delete other applications' keys, depending on adapter and namespace support. Prefer removeItem() per key, or namespace-scoped clearing if your adapter supports it. Test this before shipping.
  • Serialization applies. File and APC adapters serialize values. Closures and resources will fail; Doctrine entities with proxies can bloat or break — cache arrays, scalars, or plain DTOs instead.
  • No stampede protection. On a cold key, every concurrent request computes the value simultaneously. For expensive fallbacks, add short TTL jitter, a warmup pass, or an application-level lock.
  • Backends are period pieces. APC ≠ APCu, XCache is removed from PHP 7+, ZendData needs Zend Server. Don't plan a fresh deployment around these; plan around file, and write your wrapper so a backend swap is one constructor change.
  • Debugging: use the array adapter to isolate cache logic from backend issues; log key, hit/miss, and fallback duration in dev via your wrapper (or a decorating service); inspect files directly in cache_dir; use getMetadata() to confirm TTL and expiration on a suspect key.
  • cache:clear scope confusion — if your cache dir is under %kernel.cache_dir%, it's gone after every clear; if it's outside, nothing clears it and you must do it yourself on deploy. Pick one and document it.
  • Extension point for the eventual migration: the bundle is small (30 stars, 0 dependents, unmaintained). Keep the Zend storage behind your own wrapper interface so replacing it with symfony/cache (PSR-6/PSR-16, cache.adapter.filesystem|apcu|redis) is a one-file change. For any new project, start with symfony/cache directly — there is no reason to adopt this bundle today.
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.
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
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core