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

Psr 6 Doctrine Bridge Laravel Package

cache/psr-6-doctrine-bridge

Adapts any PSR-6 cache pool to Doctrine's legacy Cache interface. Install via Composer, then use contains, fetch, save and delete as usual; falls back to SHA-256 keys when the pool rejects a key. Includes getCachePool access.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — weak, and shrinking. This package is a one-directional shim: it adapts any PSR-6 CacheItemPoolInterface so it satisfies Doctrine\Common\Cache\Cache. It only matters if the stack actually contains Doctrine, and in Laravel that means laravel-doctrine/orm or a ported legacy module — not the Eloquent default. More importantly, the interface being adapted was deprecated in doctrine/cache 1.11 and removed in 2.0, and Doctrine ORM 2.11+/3.x consumes PSR-6 pools natively. So the bridge's addressable use case is legacy-only and contracting. The signal set (15 stars, 0 dependents, opportunity 43, no consumers to observe) says this is a commodity ~200-LOC shim, not a strategic dependency. Treat it as "buy" only because it is nearly free; treat internalizing it as an equally valid option.

Integration feasibility — cheap to try, brittle to depend on. The mechanics are trivial: composer require cache/psr-6-doctrine-bridge, then new DoctrineCacheBridge($pool) wired into Doctrine's metadata_cache_driver / query_cache_driver / result_cache_driver. The gating risk is dependency resolution, not code. Two corrections to earlier assumptions in this evaluation chain matter for planning:

  • Laravel cache stores are PSR-16 (Illuminate\Contracts\Cache\Repository extends Psr\SimpleCache\CacheInterface), not PSR-6. There is no Cache::store('redis')->getPsr6Adapter(). You must supply a real PSR-6 pool (symfony/cache RedisAdapter, cache/adapter, etc.), which adds a second cache abstraction to the stack.
  • The bridge pins doctrine/cache ^1.x (abandoned) and, in its 3.x line, likely psr/cache ^1.0. Modern Symfony/Laravel Doctrine components require psr/cache ^2|^3 and doctrine/cache ^2. If composer why-not shows a conflict, this evaluation ends here — no spike, no pilot.

Technical risk — concentrated in semantics, not performance. The adapter surface hides four behaviours that bite in production:

Risk Why it matters Severity
Key charset mismatch Doctrine keys contain \, :, @ (e.g. App\Entity\User, dc2_...) which are reserved in PSR-6. Confirm the bridge hashes keys before handing them to the pool. High
deleteAll() → $pool->clear() Doctrine's cache:clear / flush() would wipe the entire shared pool, including non-Doctrine entries. Critical
Namespace no-op setNamespace() is likely inert; two apps in one Redis DB silently collide (staging serving prod metadata). High
TTL & stats semantics Doctrine save($k,$v,0) = forever vs PSR-6 item defaults; getStats(), getNamespace() likely unsupported and throw or return empty. Medium

Key questions (to close before any commitment):

  1. Does composer require resolve against our actual Laravel/Symfony/Doctrine version set without downgrading psr/cache or doctrine/cache? (Owner: platform eng; 1 hour.)
  2. Can we run Doctrine ORM at a version that accepts PSR-6 directly, eliminating the bridge entirely? (Owner: backend lead; this is the preferred outcome.)
  3. What does the bridge do on deleteAll() against a shared pool, and can we guarantee a dedicated pool/keyspace? (Owner: backend lead; blocking.)
  4. Are keys hashed/normalised, and are entries readable across releases after a serialization change?
  5. Who owns this if upstream goes quiet — do we fork to an internal namespace (~200 LOC) as the default, or accept the external dependency?
  6. Why does the supplied metadata list a release dated 2026-08-20 while the README/CHANGELOG narrative suggests no substantive activity since 2022? (Verify on Packagist before quoting any date to stakeholders.)

Integration Approach

Stack fit — negative for a modern stack, narrow for a legacy one. The decision tree is short:

  • Doctrine ORM 2.11+/3.x present → inject your PSR-6 pool directly into Doctrine's cache drivers. The bridge adds a layer with no benefit. Do not adopt.
  • Hardcoded Doctrine\Common\Cache\Cache consumer present (older gedmo/*, older bundles, a vendored library typed against the legacy interface) → bridge is the cheapest unblock. Adopt narrowly.
  • No Doctrine at all (pure Eloquent) → out of scope; stop evaluating.

Where it does fit, always give it a dedicated PSR-6 pool mapping to a separate Redis database or key prefix from the application cache. Never share a pool with Illuminate\Cache; the clear() semantics make co-tenancy unsafe.

Migration path. Preferred sequence is "remove the need, then remove the shim":

  1. Inventory every Doctrine\Common\Cache\Cache typehint and every doctrine/cache 1.x requirement in composer.lock.
  2. Where ORM supports PSR-6 natively, migrate the consumer and delete the legacy typehint. This is the durable fix.
  3. Where a third-party package blocks step 2, wrap it behind your own thin adapter interface (App\Cache\DoctrinePool) that internally delegates to the bridge. Every future swap then touches one file.
  4. Only if the composer conflict is unresolvable and the constraint is business-critical: vendor the bridge into app/Support/Cache/ under our namespace, MIT-attributed, and drop the doctrine/cache 1.x transitive.

Compatibility checks to run, in order: composer why-not psr/cache ^3.0; composer why-not doctrine/cache ^2.0; PHP version support in the bridge's composer.json; serialization behaviour with RedisAdapter vs FilesystemCache under EntityManager::clear(). Note that array and file Laravel drivers offer no operational upside here — the value of this bridge only materialises with a shared, external backend.

Sequencing (5–6 dev-days total, most of it validation, not code):

Phase Work Exit criterion
0. Gate (0.5d) Composer resolution + why-not matrix against our real lockfile Resolves cleanly, or stop
1. Spike (2d) Wire metadata cache only; verify key charset, TTL, deleteAll() scope, cross-release read All four semantics confirmed or mitigated
2. Benchmark (1d) Bridge+Redis vs native FilesystemCache vs native PSR-6 No regression beyond noise; document numbers
3. Pilot (1–2d) Query + result cache in one non-critical service; staging soak 1 week Hit rate within 5% of baseline; no incidents
4. Rollout Remaining Doctrine caches; remove legacy cache config Legacy doctrine/cache 1.x out of lockfile

Metadata cache first — it is write-once, small, and lowest blast radius. Result cache last; it is the one whose corruption produces wrong query results rather than slow ones.

Operational Impact

Maintenance. Code maintenance is near-zero; dependency maintenance is the cost. You inherit an abandoned doctrine/cache 1.x transitively, which typically trips SCA/security review and dependency-upgrade automation. Budget an internal fork as the likely end state: it removes the abandonment risk at the cost of owning ~200 LOC that nobody outside the team reads. Whichever way you go, name a single owner in the repo's CODEOWNERS — a 15-star, zero-dependent package with no upstream SLA will not be maintained on our behalf.

Support. The on-call surface is small but non-obvious. Add three runbook entries: (a) how to flush Doctrine caches without wiping the application pool — this is the entry that prevents a 2 a.m. Redis-wide flush; (b) how to confirm keys are hashed and what a poisoned/colliding key looks like; (c) what serialization change looks like — post-deploy cache misses that never recover indicate stale-format entries, not a broken pool. Instrument hit/miss ratios per cache type (metadata, query, result) separately; a single blended metric hides result-cache regressions.

Scaling. The bridge itself is negligible — a few microseconds of array/CacheItem translation per operation, dwarfed by network RTT to Redis. The scaling story is entirely the pool: clustering, connection pooling, eviction. Watch two real hazards: cache stampede on query/result cache after deploy (PSR-6 has no locking or probabilistic early expiry in most adapters, and Doctrine's cold-cache warm-up can stampede the database), and hot keys in a small metadata keyspace. Mitigate stampede with a deploy-time warmup or jittered TTLs, not with this package.

Failure modes.

Scenario Impact Detection Mitigation
deleteAll() clears shared pool App-wide cache miss storm; DB saturation Redis FLUSHDB in logs; latency spike Dedicated pool/DB; deny cache:clear scope
Reserved-char key rejection Cache writes throw under load CacheException from pool Verify hashing in spike; otherwise wrap/escape
Namespace collision across envs Wrong-schema metadata served in prod Unexplained "column not found" errors Isolate Redis DB per environment
Legacy transitive dep flagged Blocks security sign-off / release SCA gate Internal fork; or avoid entirely
Upstream goes silent permanently No PHP/Doctrine upgrades — Fork to internal namespace now
Serialization drift across releases Permanent cache misses, not errors Hit rate never recovers post-deploy Flush on schema/model change

Ramp-up. Half a day for a mid-level engineer to wire and test; effectively zero for anyone who never touches Doctrine, since the bridge stays behind the service container. Knowledge concentration is the risk: at 15 stars and 0 dependents there is no community to ask, so the person who wrote the spike owns it until the runbook and tests exist. Budget those 2–3 days explicitly.

TPM recommendation. Do not adopt this as a platform dependency. Fund a 0.5-day gate to answer whether our Doctrine version can consume PSR-6 natively; if yes, that is the whole initiative and the package is unnecessary. If a hard legacy constraint blocks it, adopt behind an internal adapter interface with a dedicated pool and a named owner, and schedule the fork-or-remove decision into the following quarter rather than letting it become permanent. Effort is small either way (5–6 dev-days); the real cost is the abandoned transitive dependency and the shared-pool flush hazard, both of which are avoidable but only if decided up front.

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.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table