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

Annotation Cache Bundle Laravel Package

emag-tech-labs/annotation-cache-bundle

Symfony bundle that adds annotation or PHP 8 attribute based caching to service method responses. It scans services, generates proxy classes, and stores results in any PSR-6 cache implementation such as Redis, Memcache, or a simple array.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Verdict up front: do not adopt. This is a Symfony bundle, not a Laravel package, and the mechanism it relies on has no equivalent in Laravel's runtime container. For a Laravel roadmap item the correct read is "pattern reference, not dependency." For a Symfony shop it is a maybe that must clear a maintenance and dependency-health bar it currently fails.

Architecture fit

  • The bundle's entire value proposition is delivered through Symfony's compile-time container compiler passes. It scans service definitions for a @Cache annotation / #[Cache] attribute, then redefines each annotated service to point at a generated proxy subclass (via ocramius/proxy-manager) that mixes in a cache trait and overrides the annotated methods.
  • Laravel has no compile-time definition graph to rewrite. Its container resolves bindings lazily at runtime. There is nothing for a "scan services and swap the definition" pass to hook into — no Bundle, no DependencyInjection\CompilerPass, no services.yaml. The port would be a rewrite, not an integration.
  • Cache abstraction mismatch: the bundle targets PSR-6 pools. Laravel ships PSR-16 (Illuminate\Contracts\Cache\Repository). Bridging means pulling in symfony/cache or a PSR-6 adapter — new dependency surface to reproduce a capability Laravel already expresses as Cache::remember($key, $ttl, fn () => ...).
  • The proxying requirement has hard structural constraints that many real services violate: final classes and methods cannot be subclassed, private methods are invisible to the override, self::/static:: calls bypass the proxy, and PHP 8.1+ readonly properties plus constructor promotion interact badly with subclass instantiation.

Integration feasibility

  • Laravel: ~0% as-is. No service provider, no publishable config, no facade. Everything is Symfony-specific wiring.
  • Symfony: plausible but unverified. Depends entirely on whether composer.json allows symfony/framework-bundle ^6.4|^7. Last release is 2023-03-30; the Doctrine annotations pathway it was originally built on was deprecated in Symfony 5.4 and removed from the default stack in 6+.
  • Effort to replicate the behaviour in Laravel (attribute-driven method caching) is on the order of a few hundred lines — cheaper than adopting, auditing, and forking this package.

Technical risk

  • Abandoned transitive dependency. ocramius/proxy-manager is archived; the maintained successor is friendsofphp/proxy-manager-lts. Whether this bundle uses the live fork is a first-order question.
  • No adoption signal. 19 stars, 0 dependents. You would be the first production consumer. No issue history to mine for failure modes.
  • CI is legacy. Travis CI badge — the pipeline is almost certainly dead. No GitHub Actions, no Dependabot, no matrix against PHP 8.2/8.3.
  • Cache key opacity. Correctness hinges on how arguments are serialized into the key. If the key omits tenant, user, locale, or pagination context, you get cross-tenant data leakage — a security incident, not a bug.
  • No documented invalidation model. TTL-only caching with no tag support means stale reads and unbounded key growth in Redis.
  • Serialization fragility. Cached method returns must be serializable; closures, resources, PDO handles, and unsaved Eloquent state will fail at runtime, not at build time.
  • Debuggability tax. Stack traces, Telescope, and profilers attribute time and errors to generated proxy classes. Every on-call engineer pays this.

Key questions (answer these from source review before any further spend)

  1. Which Symfony versions does composer.json permit? Does it run on Symfony 6.4 / 7?
  2. Which proxy package — archived ocramius or friendsofphp/proxy-manager-lts?
  3. Exactly how is the cache key derived? Are all arguments included, and in what serialized form? Is there a configurable prefix/namespace?
  4. What is the default TTL, and can it be overridden per method?
  5. Is there any invalidation story beyond expiry — tags, manual purge, warm-up?
  6. Does the annotation path still work with doctrine/annotations removed, or is the PHP 8 attribute path the only viable one?
  7. Behaviour when the backend is unreachable — fail-open (serve uncached) or throw?
  8. Does the proxy handle final classes, interfaces, and readonly properties, or does it fail silently at build?

Integration Approach

Stack fit

Laravel primitive What the bundle expects Gap
AppServiceProvider::register() Symfony Bundle + extension No entry point
Runtime container resolution Compile-time CompilerPass + definition rewrite No equivalent phase
Cache::remember() (PSR-16) PSR-6 CacheItemPoolInterface Adapter required
$this->app->extend() decorators Generated subclass proxies Different mechanism
php artisan config:cache Symfony container dump Not comparable

Recommended path: extract the pattern, not the package.

  1. Define a #[Cache(ttl: ..., key: ...)] PHP 8 attribute in-house. Attributes are the future-proof half of this package's idea and cost nothing to own.
  2. Implement the interception with an explicit decorator, not a generated subclass. A CachingDecorator implementing the same interface as the target service, bound in a service provider, is testable, greppable, and has no final/readonly constraints. Where decoration is awkward, use Cache::remember() at the call site — it is one line and has zero onboarding cost.
  3. If the team genuinely wants attribute-driven interception, resolve it at container resolution time via $this->app->extend() or a Resolving callback that wraps the concrete — a fraction of the complexity of compile-time codegen.
  4. Enforce a key policy in code review: every cache key must include a tenant/user segment or be provably non-user-scoped.

Migration path — there is no migration, because there is no current state to migrate from. Frame the work as a reusable internal capability (2–3 day spike + tests), not a package adoption.

Compatibility — if a Symfony codebase is in scope, pin friendsofphp/proxy-manager-lts, verify against Symfony 6.4 LTS, and vendor-patch the proxy factory. Do not proceed on Symfony 7.

Sequencing

  1. Day 1–2 spike: prove the decorator approach on one real service in the Laravel app; measure hit ratio and overhead.
  2. Correctness suite: key-collision tests across tenant, locale, paginated arguments; assert no cross-user bleed.
  3. Security review: cache-key composition and serialized payload inspection.
  4. Observability: emit hit/miss/eviction metrics and key cardinality per pool; alert on cardinality growth.
  5. Kill switch: a config flag that bypasses the cache layer entirely, so an incident is a config change, not a deploy.

Operational Impact

Maintenance. This is the decisive factor. A 19-star package with zero dependents and a March 2023 release has an effective maintainer count of zero from your perspective. Adopting it means forking it, and a fork means you own the proxy generation, the annotation parsing, and the Symfony-version compatibility matrix forever. That is a permanent tax for a capability worth a few hundred lines of your own code. The Travis CI badge indicates the build pipeline is no longer exercised — treat "green" as unknown, not passing.

Support. No community, no Stack Overflow corpus, no answerable issue queue. The publishing vendor is an e-commerce company that open-sourced internal tooling; there is no commercial support path and no incentive to triage a stranger's Symfony 7 upgrade.

Scaling.

  • Build-time: proxy generation adds container-compile cost. Fine at small service counts; noticeable with hundreds of annotated services, and it requires a writable generated-code directory on every deploy target.
  • Runtime: proxy dispatch overhead is negligible relative to the cache round-trip. The real scaling risk is key cardinality — one key per unique argument tuple. A method taking a search DTO can generate effectively unbounded keys and quietly consume Redis memory.
  • Stampede: no documented request coalescing or locking. Hot-key expiry under load produces a thundering herd against the origin.
  • Invalidation: TTL-only expiry means write-through correctness is unachievable; expect "why is this stale?" incidents and no clean answer.

Failure modes to plan for

  • Backend unavailable → unhandled exception or silent fallthrough (unknown until Q7 is answered).
  • Unserializable return value → runtime SerializationException on a code path that worked before instrumentation.
  • Proxy generation fails on deploy (permissions, final class, PHP version drift) → container will not boot; whole-app outage from a caching nicety.
  • Key collision across tenants → data exposure. Highest-severity risk in the entire assessment.
  • Stale reads with no purge lever → prolonged, hard-to-diagnose correctness bugs.
  • Opcache/container-cache invalidation on deploy → intermittent failures that only reproduce in one environment.

Ramp-up. Every engineer who touches an annotated service must understand the annotation semantics, the proxy indirection, and the key-derivation rules before they can reason about behaviour. That is a real onboarding cost, paid repeatedly, for a package with no documentation beyond a README and no community to ask. Against Cache::remember(), which a new hire understands in thirty seconds, the trade is indefensible.

Bottom line for the roadmap: capture the idea — declarative, attribute-driven method caching — as an internal convention with a thin, owned implementation. Decline the dependency. If a Symfony service genuinely needs it, run the eight key questions first and treat a fork as the default outcome.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib