treehouselabs/cache-bundle
Symfony bundle that integrates caching into your application: configurable cache pools and adapters, service wiring, and straightforward cache invalidation. A low-maintenance add-on for projects that want simple, declarative cache configuration without boilerplate.
This release is a low-risk, additive update: the cache library constraint was bumped and apcu and file stores are now supported alongside the previously available drivers. There are no breaking changes, so an existing install only needs composer update and, if you want the new drivers, a config touch.
composer update --with-dependencies
composer show <vendor>/<package> # confirm v1.3.0 and the cache library version
php artisan vendor:publish --tag=package-config --force
// config/package.php
'cache' => [
'store' => env('PACKAGE_CACHE_STORE', 'file'), // now: 'file' | 'apcu' | redis | ...
'ttl' => 3600,
'prefix' => 'pkg',
],
file is the pragmatic default. It needs a writable storage/framework/cache and nothing else.apcu is the fastest option but lives in shared memory per PHP process/pool.php artisan config:clear && php artisan cache:clear, then hit the route twice and check the second request does no I/O.Where to look first: the package's cache resolver/manager class (the thing that maps your store string to a Illuminate\Contracts\Cache\Repository) if you need to know whether it uses Cache::store() or a custom adapter — this determines whether config/cache.php stores apply or only the package config does.
Define the store once in config/cache.php, reference it by name. Rather than hardcoding file/apcu in the package config, declare a dedicated store so TTLs, prefixes, and serialization are managed in one place:
// config/cache.php
'stores' => [
'package' => [
'driver' => env('PACKAGE_CACHE_DRIVER', 'file'),
'path' => storage_path('framework/cache/package'),
],
],
This makes the driver swap a pure env change between local (file), staging (apcu), and production (redis).
Environment matrix is the main workflow win. Typical split that this release unlocks for teams without Redis everywhere:
| Environment | Driver | Rationale |
|---|---|---|
| local | file |
zero infra, inspectable, survives restarts |
| CI | array |
deterministic, no cross-test bleed |
| staging | apcu |
prod-like latency without a cache cluster |
| production (multi-node) | redis / memcached |
shared state |
Warm the cache in deploy rather than on first request. Add a small artisan command or a php artisan tinker-free hook into your deploy script so the first user after a release doesn't pay the cold-start cost:
// app/Console/Commands/WarmPackageCache.php
public function handle(): void
{
$this->call('cache:clear'); // only if the payload schema changed
// iterate the hot keys and re-populate via the package API
}
Invalidate on domain events, not on a timer. If the package caches derived data, hook saved/deleted model events or your domain events to forget the affected keys. With file/apcu you cannot lean on tag flushing, so keep keys derivable and forget them explicitly.
Test against the real driver at least once. Run the suite on array, but add one integration test that boots with file to catch serialization and permission problems that array hides.
Gate the driver per feature if you mix. Nothing stops you from using apcu for hot config and file for larger payloads; the new support makes that a config decision rather than a code change.
apc.enable_cli=0 means queue workers, artisan commands, and any CLI-triggered test see an empty (or unavailable) cache while web requests see a warm one. This is the single most common "it works in the browser, not in the job" bug after enabling apcu. Set apc.enable_cli=1 in the CLI ini if you genuinely need it, or keep CLI paths on file.php-fpm reload. Never treat it as durable, and never use it behind a load balancer with more than one node.apcu extension should not surface as a silent cache miss on every request.file cache and permissions. The directory must be writable by both the web user and the CLI user (deploy scripts, queue workers). Mixed ownership produces intermittent write failures that look like cache misses. Use a dedicated subdirectory and check it in your deploy smoke test.file on shared storage is not a cache. NFS/EFS-backed storage/ gives you cross-node "sharing" with locking and latency problems. If you need multi-node, use Redis — file is a single-host tool.file/apcu. Cache::tags() will throw or silently degrade depending on the store. Design keys so invalidation is by explicit forget() or a version prefix (pkg:v2:...) that you bump on schema change.composer why <cache-library> and check nothing else pins the old version; a transitive downgrade or a major bump in the cache library can change serialization or TTL semantics even though the package's own API is unchanged.php artisan config:cache bakes the store name in; a stale cached config is a frequent cause of "I changed the env and nothing happened". Follow any env change with config:clear (or re-run config:cache) and queue:restart for workers.0/null semantics per driver. file and apcu handle "forever" differently from Redis; if the package passes your TTL straight through, verify a null TTL doesn't mean "expire immediately" on the new stores.composer update.How can I help you explore Laravel packages today?