phy/cache-bundle
phy/cache-bundle is a PHP/Symfony cache bundle that provides configurable cache services and a straightforward API for storing, retrieving, and invalidating cached data in your application. It helps reduce repeated work and speed up responses with minimal setup.
This is a Symfony2 bundle, not a Laravel package. There is no service provider, no facade, and no composer require drop-in for a Laravel app. If you are on Laravel, treat this as reference material for how a multi-adapter cache abstraction was wired prior to PSR-6/PSR-16 — you will be reimplementing the idea with Illuminate\Cache and Laravel's store drivers (which already cover APC, Memcached, Redis, file, and array). If you are maintaining a legacy Symfony 2.x codebase, the assessment below applies.
Install (Symfony2 project only):
composer require phy/cache-bundle
Register the bundle in app/AppKernel.php:
public function registerBundles()
{
$bundles = array(
// ...
new Phy\CacheBundle\PhyCacheBundle(),
);
}
Look first at:
DependencyInjection/Configuration.php — this is where the adapter choices (apc, memcache, memcached, redis, local, disk) and their connection settings are defined. Read it before touching YAML.Resources/config/services.xml (or .yml) — the service IDs and aliases are here. The bundle typically exposes a cache service you inject; confirm the exact ID before wiring.Resources/doc/ — if present, this is usually the only accurate usage reference for low-adoption bundles.First use case: wire a single adapter, inject the cache service into one service, and cache an expensive read.
# app/config/config.yml
phy_cache:
adapter: redis # or apc / memcache / memcached / local / disk
redis:
host: 127.0.0.1
port: 6379
namespace: myapp_dev # keep env-scoped
Then inject the bundle's cache service by its service ID/alias and call get/set/delete/flush as exposed by the adapter wrapper. Always confirm the method signatures against the adapter class in Cache/ before relying on them — this bundle predates any interface standard, so adapters may not be perfectly interchangeable.
Pick the adapter by environment, not by code path. The bundle's value proposition is that you change the adapter in config, not in your domain code. Structure your services to depend on the cache abstraction, and swap local (Symfony array/local cache) in test, disk or apc in dev, redis/memcached in prod. Never if ($adapter === 'redis') in a service.
Wrap the bundle service behind your own interface. Because the underlying adapter methods are not standardized, create a thin domain interface in your app and write one implementation that delegates to the bundle:
interface ArticleCache
{
public function remember(string $key, int $ttl, callable $resolve);
public function forget(string $key): void;
}
This means when you eventually migrate off this bundle (likely, given age and adoption), you only rewrite one class.
Cache-aside in services, not controllers. Inject the cache into repositories/query services. Keep controllers free of cache keys so the same key logic is reused by console commands and queue workers.
Namespacing discipline. Use a prefix per bounded context and per environment (articles:prod:, sessions:prod:). Since the bundle may or may not add its own prefix, add one at the call site:
$key = sprintf('articles:%s:%d', $env, $id);
Cache warming via a console command. Run a cache:warm-style command that iterates hot records and populates the adapter selected in config. Because local is per-process, warming only makes sense for shared backends (redis, memcached, apc in mod_php).
Compose with Symfony's own cache. If you're on Symfony 2.4+, symfony/cache and Doctrine\Common\Cache cover a lot of ground. Use this bundle only where you specifically need its bundled adapter set — otherwise prefer Symfony's DoctrineCacheBundle so you stay on a maintained path.
Integration with Symfony services:
app.article.repository:
class: AppBundle\Repository\ArticleRepository
arguments:
- "@doctrine.orm.entity_manager"
- "@phy_cache" # verify this ID in services.xml
Illuminate\Support\Facades\Cache with redis/memcached/file stores instead — this bundle adds nothing a Laravel dev can install.apc needs ext-apc (disabled on PHP 7+ in favor of APCu); memcache needs the old ext-memcache, not ext-memcached; memcached needs ext-memcached; redis needs a Redis server and the client the bundle expects (likely predis or ext-redis — check composer.json). These distinctions bite in CI images.composer why-not phy/cache-bundle and checking the composer.json PHP constraint is a five-minute sanity check that saves hours.disk/file and redis may round-trip objects differently from apc (which, in-process, can behave differently with references). Cache scalars/arrays in preference to complex domain objects; if you cache objects, use a versioned key so schema changes don't deserialize stale classes.local/array cache is per-request. Don't treat it as a shared cache in tests or long-running workers — it will behave nothing like redis. Assert against the shared adapter in integration tests.0 or null TTL as "no expiry", others as "expire immediately". Pin explicit TTLs in your wrapper.sha1($key)) with a short readable prefix when using memcache(d).flush() clears other people's keys. Prefer tagged or namespaced invalidation; if the bundle has no tag support (likely), maintain a version token per namespace and bump it on deploy.INFO cache adapter = redis namespace = myapp_dev) — silent fallback to local after a misconfigured adapter is a classic "why is it slow in prod" symptom. Confirm the selected adapter class from the compiled container: php app/console container:debug | grep -i cache.phy_cache.adapter tag, a compiler pass, or an interface to implement). If it does, prefer adding an adapter over forking; if it doesn't, wrap the service instead.How can I help you explore Laravel packages today?