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 Messenger Bridge Laravel Package

trollbus/symfony-messenger-bridge

A bridge between Trollbus and Symfony Messenger that lets Trollbus applications reuse Messenger messages, handlers, middleware, and transports, simplifying interoperability and gradual migration between the two messaging systems.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a 0.1.0 release — the first public tag. There is no prior assessment and no migration path to worry about, but also no battle-testing: treat the public API as unstable until 1.0 and pin the exact version in composer.json ("trollbus/symfony-messenger-bridge": "0.1.*").

Install and publish:

composer require trollbus/symfony-messenger-bridge:^0.1.0
php artisan vendor:publish --tag=messenger-config   # verify the tag in the service provider

Where to look first, in this order:

  1. composer.json — confirm which symfony/messenger major it requires and whether symfony/messenger is a hard dependency or a suggest. This determines whether you're buying into the full Symfony component or a thin wrapper.
  2. The service provider (src/*ServiceProvider.php) — check what it binds into the container: a MessageBusInterface, a RoutableMessageBus, an event dispatcher adapter, and whether it auto-registers middleware. This is the real API surface.
  3. config/messenger.php (if published) — default_bus, buses, transports, routing, failure_transport. This mirrors Symfony's messenger.yaml; map it mentally onto the Laravel config cache.
  4. The README examples — 0.1.0 packages usually have one happy-path snippet; that is the "supported" usage.

First use case to validate end-to-end: dispatch a trivial command to the sync transport and assert the handler ran, then switch the same message to a real transport (database or Redis) and confirm messenger:consume-style consumption works. Doing the sync case first isolates wiring bugs from transport bugs.

Implementation Patterns

Command/query separation via multiple buses. The typical setup is a command.bus and a query.bus with different middleware stacks — commands get transaction wrapping and retries, queries get nothing. Configure them under buses in config, then inject by name:

public function __construct(
    #[Target('command.bus')] private MessageBusInterface $commandBus,
) {}

If the package's container binding doesn't support attribute targeting, fall back to contextual binding in a service provider.

Handler registration. Two patterns are common with bridges: explicit messenger.handlers config mapping message class → handler service, or Laravel-style auto-discovery via a #[AsMessageHandler]-equivalent attribute/tag. Prefer the explicit mapping in 0.1.x — auto-discovery in a young package tends to miss handlers in vendor packages and cached config.

Routing vs. dispatch() with a transport argument. Put durable routing in config (routing: [SendInvoice::class => 'async']) so it survives refactors and is visible in one place; reserve $bus->dispatch($msg, [new DelayStamp(60)])-style stamps for per-dispatch concerns (delay, priority). Mixing the two — stamping a transport that also has a config route — produces confusing double-sends.

Transaction safety. If you dispatch inside a DB transaction, wrap the dispatch in the bridge's transaction middleware (or dispatch after commit). With the database transport this matters most: the worker can pick up the message before the transaction commits and read stale/no data.

Failure handling. Configure a failure_transport and treat it as a real operational queue, not a bin — you'll want a messenger:failed:show / retry equivalent wired into your ops runbook, and an alert on failure-transport depth. Retries are stamp-based (RetryStrategy); per-message overrides go on the message class, not in the dispatch call, if you want them to survive retries.

Scheduling and workers. Run consumers as long-lived processes under Supervisor/Horizon-adjacent tooling, not as cron --once jobs. In local dev, a --limit/--time-limit flag is your friend to avoid zombie workers after deploys.

Testing. Use the sync transport in phpunit.xml env so handlers execute inline and assertions are trivial; keep one integration test per transport that actually asserts a message round-trips through the real broker.

Gotchas and Tips

  • Config caching. If the provider reads Symfony-style config at boot rather than through Laravel's config(), php artisan config:cache can silently deserialize stale transports. Verify with config:cache then config:clear in staging before deploy.
  • Pre-1.0 churn. No BC promise. Read the diff of every 0.1.x patch rather than trusting semver — patch releases here can rename config keys or attributes.
  • Two service containers. The bridge has to reconcile Symfony's ContainerInterface with Laravel's. If a handler is registered in Symfony's handler locator but not resolved from Laravel's container, you get "no handler for message" errors that look like routing bugs. Check both.
  • Middleware order. Symfony middleware is first-in/last-out around the handler; Laravel developers often assume the opposite. dispatch_after_current_bus and send_message middleware must sit at the right ends or messages get double-dispatched or never sent.
  • Serialization. The default PHP serializer will break on messages holding Eloquent models or closures. Use primitive payloads / DTOs, or switch to the Symfony serializer and be explicit about the message namespace mapping. Never put a model in a queued message.
  • Worker restarts on deploy. Long-lived consumers hold old code in memory. Add php artisan queue:restart-equivalent (or a file-touch sentinel) to your deploy script, or schedule the consumer with --time-limit.
  • Duplicate consumption. At-least-once is the default contract. Make handlers idempotent (unique constraint, processed-message table) before you scale past one worker.
  • Observability gap. The bridge likely does not integrate with Laravel Telescope or Horizon out of the box. Add a middleware that logs message class, transport, attempt count, and duration — you will need it the first time a message vanishes.
  • Debugging lever. When a message disappears, check in order: routing config → transport DSN reachability → worker logs → failure transport. Nine times out of ten it's a DSN typo or an unrouted message class falling through to the default bus.
  • Extension points to confirm before building on them: a MessageBus decorator binding, a middleware registration hook, and an event dispatched on send/fail. If any of those are absent, file an issue now while the maintainer is still shaping the API.
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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource