cache/doctrine-adapter
This package adapts legacy Doctrine\Common\Cache implementations to PSR-6 and PSR-16, letting existing Doctrine caches work with modern cache pools. Version 3 changes the tagged-item format, so drain workers and clear the cache before upgrading or rolling back.
Architecture fit. The package solves one direction of a two-way problem: it exposes a legacy Doctrine\Common\Cache\CacheProvider behind a PSR-6 CacheItemPoolInterface (DoctrineCachePool). That is the opposite orientation from what a typical Laravel stack needs. Laravel's cache layer is Illuminate\Contracts\Cache\Repository / Illuminate\Cache\Store — it is neither PSR-6 nor PSR-16 compliant, and there is no first-party bridge that lets Cache::put() / Cache::remember() delegate to a PSR-6 pool. Consuming this package in Laravel therefore means writing a custom Store implementation that adapts back from Laravel to PSR-6 to Doctrine, i.e. two adapters in the hot path. The genuinely common Laravel need — "make Doctrine ORM result/metadata caches use Laravel's Redis/Memcached cache" — is served by the sibling package cache/doctrine-bridge (PSR-6 → Doctrine), which should be evaluated first.
Integration feasibility. Technically trivial (one class, MIT, composer require cache/doctrine-adapter). Practically constrained by three hard facts:
doctrine/cache 1.x. The Doctrine\Common\Cache API is deprecated and removed in doctrine/cache 2.x, so the adapter's entire substrate is sunset. Adopting it commits us to an EOL dependency line.{ } ( ) / \ @ : in keys. Laravel-generated keys routinely contain : (Eloquent model keys, tag identifiers, default prefixes). A sanitising/escaping decorator plus length-hashing (Memcached's 250-byte key limit) is a mandatory prerequisite, not a nice-to-have.cache/taggable-cache); Doctrine providers themselves have no tag support. Any plan that assumes Cache::tags() maps onto Doctrine is built on sand.Technical risk. High relative to the value delivered. Ecosystem signal is weak: 13 stars, 0 dependents, read-only subtree split of a monorepo, low org velocity. Bus factor is effectively one org. Runtime risks: getItems() degrades to N sequential fetches because CacheProvider has no multi-get (latency amplification on request paths that read many keys); saveDeferred/commit semantics are emulated; failure behaviour (fail-open vs fail-closed) is inherited from whichever Doctrine provider is wrapped and is undocumented.
Key questions.
cache/doctrine-bridge), rather than the reverse?Store adapter and the key-sanitisation layer, and what is its test surface?doctrine/cache 1.x is dropped, and how many call sites does that touch?cache/taggable-cache acceptable as an additional dependency with its own invalidation semantics?redis driver under realistic key-fan-out?Stack fit. Poor-to-conditional. Laravel's native redis, memcached, dynamodb, and database stores already cover the operational cases this adapter would serve, with first-party support and observability. The adapter only fits when there is a pre-existing, non-negotiable Doctrine cache provider — for example a legacy Doctrine ORM install with tuned Memcached namespaces — that a PSR-6 consumer must now share. Outside that narrow window it is added complexity with no user-visible benefit.
Migration path. Do not migrate to this package directly. Instead:
DoctrineCachePool behind a custom Illuminate\Cache\Store, wire one non-critical cache namespace, and measure the delta against the current driver.cache/doctrine-bridge instead.Compatibility. Requires doctrine/cache 1.x; verify it does not collide with doctrine/dbal / doctrine/orm constraints in composer.lock (composer why-not cache/doctrine-adapter). Pin exact versions. Confirm the wrapped provider has a maintained PHP-extension story (Memcached/APCu) for the runtime images we ship.
Sequencing. Spike → direction decision (go/no-go gate) → sanitiser + Store adapter with contract tests → single-namespace pilot behind a config flag → expand only if p95 and hit-rate parity hold. Treat every gate as a real stop point; the default outcome should be "no."
Maintenance. The dominant cost. We would own the Laravel-side Store adapter, the key sanitiser, and the eventual migration off doctrine/cache 1.x — none of which the upstream package covers. Upstream is a thin, stable, but effectively frozen wrapper; assume no feature support. Budget for a fork or vendored copy rather than relying on issue resolution.
Support. No meaningful community: negligible stars, zero dependents, single-organisation maintenance, read-only split repo. Internal runbooks, not Stack Overflow, will be the support model. Escalation path is "we patch the fork."
Scaling. Throughput tracks the underlying Doctrine provider minus per-operation overhead from PSR-6 item hydration. The material concern is fan-out: getItems() cannot batch against CacheProvider, so pages that warm dozens of keys issue dozens of round trips. For high-traffic read paths this is a latency and connection-pressure risk that native drivers do not carry. Validate with realistic key fan-out, not single-key microbenchmarks.
Failure modes. Undefined and provider-dependent: connection loss, silent false returns, and exception propagation all behave differently across Memcached/Redis/APCu wrappers. We must explicitly choose fail-open (serve uncached, log) or fail-closed, and test it. Secondary risks: key-sanitiser collisions silently serving the wrong payload (mitigate with collision assertions in tests), key-length truncation, and cache stampede where the wrapped provider lacks atomic add-style locking. Instrument hit/miss ratio, p95 latency per store, and sanitiser collision count before rollout.
Ramp-up. Low technical ramp (one class), non-trivial organisational ramp: the team must understand PSR-6 semantics, legacy Doctrine cache semantics, and the deprecation timeline simultaneously. Expect a half-day of onboarding plus the sanitiser/adapter build. The real cost is the standing obligation to revisit this when doctrine/cache 2.x forces the issue.
Recommendation. Do not adopt as a default. Approve only as a scoped bridge for a specific, named legacy Doctrine provider, with a documented exit plan and an owner for the Laravel←PSR-6←Doctrine adapter chain. Otherwise, standardise on Laravel's native drivers and, if Doctrine interoperability is the actual requirement, evaluate cache/doctrine-bridge — the direction that matches the problem.
How can I help you explore Laravel packages today?