php-extended/php-simple-cache-filesystem
A filesystem-backed PSR-16 simple cache implementation for PHP. Store and retrieve cache items as files with TTL support, offering a lightweight, dependency-free way to add persistent caching to Laravel or any PHP project.
What the package is: A leaf-level PSR-16 (Psr\SimpleCache\CacheInterface) implementation backed by the local filesystem. No Laravel service provider, facade, config file, Artisan command, or event integration. Its entire public surface is the eight PSR-16 methods (get, set, delete, clear, getMultiple, setMultiple, deleteMultiple, has).
Architecture fit: Structurally it is a utility library with no framework coupling, so it would technically "fit" anywhere a PSR-16 contract is required. The problem is that it competes with a first-party capability rather than extending one: Laravel's own Illuminate\Cache\Repository already satisfies Psr\SimpleCache\CacheInterface, and the built-in file store already provides filesystem-backed caching with config integration, tagging, locks, events, and framework-level observability. For a standard Laravel application the net new capability is effectively zero, while the net new surface (a second cache implementation, a second on-disk cache directory, a second failure domain) is non-trivial.
Integration feasibility: Mechanically installable via Composer if the package is published to Packagist; if not, it requires a VCS repositories entry, which is a permanent maintenance tax on every build. There is no out-of-the-box container binding, so adoption means writing and owning a service provider regardless. The most likely binary blocker is a PSR-16 version mismatch: implementations authored against psr/simple-cache ^1.0 do not declare the return types required by ^3.0, and Composer will refuse to install the pair. Whether this package's constraint permits coexisting with the modern interface release is the first thing to verify — if it forces a downgrade of psr/simple-cache across the whole application, that alone ends the evaluation.
Technical risk (high, concentrated in provenance): Zero stars, zero dependents, and a score of 0 means there is no community validation, no downstream consumers exercising edge cases, no third-party security review, and no evidence of a maintenance cadence. Bus factor is one. For a component that will sit on the hot path of request handling and write attacker-influenced keys to disk, that is a poor risk profile relative to alternatives with thousands of dependents (symfony/cache, cache/filesystem-adapter).
Filesystem-specific risks to validate in code review:
rename semantics.{ } ( ) / \ @ :; a naive passthrough invites path traversal and directory spraying.unserialized without allowed_classes restriction, any writer to the cache directory gains object-injection primitives.0777 umbrella here is a finding, not a nit.clear() is O(1) or a recursive walk.Key questions: Is the package on Packagist, under what license, and what is the last commit date across the dependency tree (not just this repo)? What psr/simple-cache constraint does it declare? Does it pull in a dozen sibling php-extended/* interface packages? What problem in our codebase actually requires a PSR-16 implementation that Laravel's cache cannot serve?
Recommendation: Reject for the primary caching path. Consider only for a narrow, non-critical, isolated use case where a PSR-16 dependency must be satisfied outside the Laravel cache layer — and even then, cache/filesystem-adapter or symfony/cache are safer picks on adoption signals alone.
Stack fit: Keep Laravel's configured default store untouched (CACHE_DRIVER=redis in production, file locally). This package should never be bound as the application-wide Illuminate\Contracts\Cache\Repository; doing so silently strips tagging, locks, and cache events from every caller.
Do not bridge it to Illuminate\Contracts\Cache\Store. The PSR-16 contract and Laravel's Store contract differ on TTL semantics, has, clear, and increment/decrement; writing an adapter is more code than the package saves and creates a translation layer with its own bug surface. If PSR-16 injection is genuinely needed, bind the interface directly — Psr\SimpleCache\CacheInterface — scoped to a named instance and an isolated directory, and leave the Cache facade alone.
Migration path (strangler, not cutover):
Cache repository and ship that. This proves the seam without a new dependency.Compatibility gates before any merge:
psr/simple-cache constraint resolution against the full composer.lock; run composer why psr/simple-cache and confirm no version pinning cascade.igbinary, msgpack) declared as hard requirements.MAX_PATH).Sequencing: (1) provenance and license check, (2) dependency-tree diff and package-count delta, (3) run a PSR-16 conformance suite — the cache/integration-tests PSR-16 suite is the cheapest way to expose TTL and multi-key bugs, (4) pilot in one subsystem with a dedicated cache directory and a feature flag, (5) observe two sprints, (6) decide. Do not sequence this ahead of higher-opportunity work; the opportunity score of 35.77 correctly signals low leverage.
Maintenance: Assume fork-on-adopt. With no stars and no dependents, there is no upstream pressure to fix the bugs you find, and no guarantee a PHP 8.4/9.0 compatibility release will ever land. Budget for vendoring the package or replacing it within 12–18 months. Track it in the dependency register as "at-risk, single maintainer, unpatched-fork candidate."
Support: No SLA, no commercial backing, documentation limited to generated API docs. Internal on-call owns every incident involving it from day one.
Scaling: Node-local by design. It does not provide cross-node consistency, so any horizontally scaled deployment gets per-instance cache divergence — acceptable for derived/regenerable data, incorrect for anything requiring invalidation guarantees. Watch disk I/O, inode consumption on many-small-file workloads, and clear() cost on large trees: a recursive delete of hundreds of thousands of files is a blocking operation that can stall a request worker and, on shared volumes, saturate I/O. No async GC means expiry cleanup must be handled by a scheduled job we write ourselves.
Failure modes and mitigations:
allowed_classes, keep the directory outside the webroot, set 0700/0600.Ramp-up: Developer ramp-up is trivial — eight methods, PSR-16 is well understood, a competent engineer is productive in under an hour. Operational ramp-up is the real cost: a new disk surface to monitor, a retention/cleanup policy to design, permissions to enforce in the container image, a runbook entry for cache-corruption incidents, and a documented fallback path. Estimate one to two engineer-days to integrate and instrument, plus recurring ownership — against an alternative (Laravel's native file store) that costs approximately zero on both axes.
How can I help you explore Laravel packages today?