madewithlove/illuminate-psr-cache-bridge
A lightweight adapter that exposes Laravel's Illuminate cache stores as a standard PSR-6 cache pool, so libraries depending on PSR-6 interfaces can reuse your existing Laravel cache configuration and drivers without adding new backends or duplicating setup.
Architecture fit. The package is a narrow adapter: it implements Psr\Cache\CacheItemPoolInterface (and CacheItemInterface) by delegating to an Illuminate\Contracts\Cache\Repository / Store. That is exactly the right shape for the problem it solves — a third-party library demands PSR-6, the application already standardized on Laravel's Cache, and nobody wants two cache subsystems with divergent TTLs, key namespaces, and flush semantics. The abstraction boundary is small and well understood; the wrapper does not own data, configuration, or lifecycle. Conceptually this is low-coupling, low-blast-radius glue.
Integration feasibility. Registration is trivial — a container binding that wraps cache()->store(...) in the pool class, injected wherever the consuming library takes a CacheItemPoolInterface. No service provider magic, no config publishing, no schema. The real feasibility question is compatibility, not integration effort.
Technical risk. The dominant risk is staleness, not design:
| Risk | Assessment |
|---|---|
| Last release 2019-07-01 | ~6 years dormant. Predates PHP 8, psr/cache 2.0/3.0 (which added static/typed returns), and Laravel 7–12. Composer constraints may hard-fail on modern PHP; --ignore-platform-reqs is not a production strategy. |
| PSR-6 spec compliance | getItem must return a hit/miss item even for stored null; Laravel's has()/get() conflate "missing" and "null." Key validation (reserved {}()/\@:), getItems/deleteItems batching, and saveDeferred/commit semantics must be explicitly verified, not assumed. |
| TTL fidelity | PSR-6 takes `DateTimeInterface |
| Adoption signal | 84 stars, effectively single-maintainer. Bus factor ≈ 1, no vendor SLA, no security response path. |
| Size | The adapter is likely a few hundred lines. The buy is convenience, not capability. |
Key questions to resolve before committing.
psr/cache ^1.0 only, or ^1|^2|^3?saveDeferred/commit genuinely supported, or silently no-op?getItems/deleteItems batched or N+1 loops against the store?flush() a loaded gun)?Stack fit. Additive and non-invasive: no changes to existing cache usage, no dual-write, no data migration. The bridge only serves the specific consumer(s) that require PSR-6; everything else keeps using the native facade. That keeps the blast radius to one dependency edge.
Migration path. There is nothing to migrate — only a binding to introduce. The realistic decision is adopt vs. fork vs. build:
psr/cache and PHP constraints, add the missing compliance behavior, and run the PSR-6 integration test suite against it. Cost is measured in days, not weeks.Compatibility. Treat 2019-era support as unverified. Concretely: run composer why-not against our platform packages, then execute the official cache/integration-tests suite (or equivalent) against Redis and a non-TTL store (array/file) to expose semantic gaps.
Sequencing.
flush scoping.CacheItemPoolInterface as a singleton in a service provider; pin an explicit store (do not inherit the default store implicitly).flush() in shared environments; add an observability hook or at least a metrics assertion.Maintenance. Lowest-cost surface in the stack — a thin adapter with essentially no configuration drift — but the upstream maintenance burden is effectively ours. Budget for an annual compatibility review, and assume a fork within 12 months if the repo stays dormant. MIT licensing makes that legally frictionless; the cost is ownership, not permission.
Support. Community-only. No security disclosure process, no versioning guarantees, no maintainer responsiveness commitment. For an internal-only, non-customer-facing dependency that is tolerable; for anything in a regulated or audited path it is a finding.
Scaling. The bridge contributes ~one function call of overhead — negligible. Scaling behavior is entirely the underlying Laravel store's (Redis/Memcached scale fine). The one real scaling hazard is batching: if getItems/deleteItems are implemented as loops, bulk access becomes N round-trips where the native client would issue one MGET. That is invisible at low volume and painful under load. Verify and, if needed, override.
Failure modes to design against.
null read back as a miss, causing repeated upstream calls.flush() blast radius — a PSR-6 consumer calling clear() and evicting the entire shared store. Highest-severity failure here; mitigate with a dedicated store or namespace.saveDeferred without commit (or a no-op implementation) quietly dropping entries.Ramp-up. Very low for usage — an engineer productive in under an hour. Higher for safe ownership: auditing against the PSR-6 spec and Laravel cache internals (TTL units, has() semantics, store-specific behavior) is the real cost, on the order of a day for an unfamiliar engineer. Document the store binding, key namespacing, and the flush prohibition at the point of registration.
Bottom line. Architecturally correct, operationally cheap, strategically stale. I would not adopt the upstream package into a production path on a modern stack without a fork and a compliance test pass — but the fork is small, the license permits it, and the alternative (a second cache subsystem, or hand-rolling the adapter) is worse. Score 0.76 is fair: good idea, unmaintained execution.
How can I help you explore Laravel packages today?