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

Symfony Aop Coroutine Bundle Laravel Package

tourze/symfony-aop-coroutine-bundle

Symfony bundle that adds coroutine support to your application through AOP. It registers aspects and interceptors so services transparently run inside coroutine contexts, making Swoole-style concurrency easier to integrate while keeping your Symfony code clean and annotation-driven.

View on GitHub
Deep Wiki
Context7

Getting Started

This release (1.0.2) is a patch bump from 1.0.1, and the only published artifact is a compare link — there are no release notes describing fixes, features, or deprecations. Treat 1.0.2 as a rebuild of 1.0.1 until you've diffed the two tags yourself. Nothing here signals a breaking change, so there's no migration work implied; there's also nothing new to adopt.

Before writing any code, resolve one thing: this is a Symfony bundle, not a Laravel package. Laravel has no bundle system, no config/bundles.php, and no service-container compiler passes of the kind AOP weaving depends on. So the first decision is whether you're:

  1. Working in a Symfony app/service (then use it normally), or
  2. Trying to get AOP + coroutine semantics inside a Laravel app — in which case you cannot install this as-is and should plan on a bridge (HTTP/RPC call to a Symfony-hosted service, or a hand-rolled decorator/middleware equivalent in Laravel).

Where to look first, in this order:

  • composer.json — the two names that matter are the AOP engine and the coroutine runtime (Swoole, Swow, or a Fiber/Revolt-based runtime). That pair determines almost everything about how you'll deploy and debug.
  • src/DependencyInjection/ — the extension plus any compiler passes tell you what gets registered and, critically, which services get woven/proxied.
  • src/Attribute/ (or src/Annotation/) — the attributes you actually put on your classes. This is your day-to-day API surface.
  • README examples — run the smallest one end-to-end before designing anything around it.

Canonical first use case: take an existing service method that does slow I/O (a remote API call, a DB round-trip), and get two things without touching the method body — concurrent execution via a coroutine boundary, and cross-cutting behavior (retry, timing, locking, tracing) via an attribute. If you can't get that working on a throwaway service, stop there.

Implementation Patterns

Attribute-first interception. The idiomatic usage is to annotate a service class or method, and let the container hand you a proxy. Two rules follow immediately: the class must be container-managed (never new it yourself, or you get the raw, unwoven object), and you should inject the interface rather than the concrete class so the proxy can substitute cleanly.

Push the coroutine boundary to the edge. Put the coroutine at the entry point — controller, console command, or message-worker loop — and keep inner service classes coroutine-agnostic wherever possible. Code that only runs inside an established coroutine doesn't need to know it's in one; code that starts one should be a small, obvious number of places.

Separate the two concerns. AOP advice and coroutines solve different problems and are easy to conflate:

  • Advice for cross-cutting policy: retry with backoff around a flaky remote call, timing/metrics, distributed locking, circuit-breaking.
  • Coroutines for concurrency: fanning out N independent remote calls, or overlapping I/O that's currently sequential.

Writing the retry logic inline in a coroutine method and calling it "AOP" is the common anti-pattern; the value of the attribute is that the policy is declared once and applies uniformly.

Composition. Advice should compose in a predictable order (outermost = locking/tracing, then retry, then the actual call). Establish and document that order early — with weaving, the visual order of attributes on a method is not always the execution order, so verify rather than assume.

Testing. Test the real service implementation directly (unit), and test each advice class in isolation as a plain object. Don't write tests that depend on the proxy being present — they're slow and they break when weaving config changes.

Bridging to Laravel. If the goal is Laravel, the realistic patterns are: (a) run the Symfony service separately and call it over HTTP/queue, or (b) reimplement the specific advice as a Laravel middleware, job middleware, or a decorator bound in a service provider. Option (b) gets you the cross-cutting behavior and none of the coroutine concurrency — Laravel's request model doesn't give you a place to park a coroutine runtime without a long-running worker (Octane, queue worker), which is a much larger change than installing a package.

Gotchas and Tips

No release notes. The 1.0.2 changelog is a bare compare URL. Before upgrading, actually read git diff 1.0.1..1.0.2 — check composer.json for changed dependency constraints (a patch bump that silently raises a runtime version is the classic way to break a deploy), and skim src/DependencyInjection/ for anything that alters what gets woven. Semver says low risk; the empty notes mean you verify rather than trust.

Bundle vs. package friction. There's no vendor:publish, no config/app.php provider entry, no Laravel service provider. Anything in the docs referencing config/bundles.php, services.yaml, or compiler passes is Symfony-only. This trips people up when they find the package via a generic "AOP in PHP" search.

AOP blind spots — these will silently give you the un-proxied behavior:

  • final classes and final methods (proxies can't subclass them).
  • private, protected (in some engines), static methods.
  • Internal $this->otherMethod() calls — the call doesn't re-enter the proxy, so nested advice doesn't fire.
  • Objects created with new, or resolved from the container before the extension registers.
  • Classes registered as lazy/compiled in ways the pass skips.

When an attribute "does nothing," check whether the service is actually a proxy before you debug the attribute itself. Dumping the compiled container is the fastest way to confirm.

Coroutine state leakage. This is the highest-severity failure mode and it's invisible in single-request testing. Any request-scoped data stored on a singleton service, a static property, or a global is shared across concurrent coroutines. Authenticated user, tenant ID, locale, correlation IDs — all of it. Use a coroutine-local context object rather than injecting Request or reading globals deep in the call stack. If you're bridging Laravel facades into a coroutine runtime, audit them for exactly this; several hold per-request state.

Blocking calls stall the worker. A synchronous DB driver, file_get_contents, sleep, or a non-async HTTP client inside a coroutine blocks the entire worker, not just that coroutine. Under load this looks like random, total stalls rather than slowness. Verify every I/O dependency in the call path has an async-compatible driver.

One container, many coroutines. The container boots once and lives for the worker's lifetime. Services must not accumulate state across invocations. Anything that worked "by accident" under PHP-FPM (fresh process per request) will now persist.

Debugging. Weaving and proxies obscure the real stack trace. Practical moves: log entry/exit from each advice with a correlation ID, temporarily disable weaving for one service to confirm it's the culprit, and keep advice classes tiny so they're trivially unit-testable.

Extension points worth knowing. Compiler passes (to control what gets woven and how), custom attributes + their advice classes (to add your own cross-cutting policy), and the runtime configuration for the coroutine scheduler (worker/concurrency counts — tune these against your actual DB connection pool, which is usually the real ceiling, not CPU).

Upgrade hygiene. Pin the version. With a 1.0.x line and no changelog discipline, an unpinned ^1.0 will pull changes you can't audit from the release page.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource