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

Rabbitmq Bundle Laravel Package

nti/rabbitmq-bundle

nti/rabbitmq-bundle integrates RabbitMQ messaging into Symfony applications, providing services and configuration for publishing and consuming AMQP messages. It simplifies connection setup, queue and exchange declarations, and producer/consumer wiring so PHP apps can add reliable asynchronous messag...

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package — there is no service provider, no auto-discovery, no config/rabbitmq.php merge. From a Laravel developer's perspective the realistic first step is a decision:

  1. If you just want RabbitMQ as a Laravel queue backend, stop here and use a Laravel-native driver such as vladimir-yuldashev/laravel-queue-rabbitmq (wraps php-amqplib, plugs into Queue::push, workers, failed jobs). It gives you 90% of what this bundle is for, without Symfony plumbing.
  2. If you need raw AMQP control — explicit exchanges, bindings, fanout pub/sub, RPC, dead-letter topologies — the value of this package is the shape of its config, not its Symfony glue. Read its config schema as documentation, then talk to php-amqplib directly from a Laravel service class. That is usually cleaner than importing a Symfony bundle into a modern Laravel app.

Where to look first (if you do pursue it):

  • The bundle's DI extension config schema (nti_rabbit_mq.connections / producers / consumers). Treat it as a cheat-sheet: each producer is an exchange + routing key + AMQPMessage flags; each consumer is a queue + callback + qos settings.
  • The connections node — since v1.15.1 it accepts multiple hosts per connection, which is worth copying into your own connection factory design.
  • Producer / Consumer / Connection classes — this is thin sugar over AMQPLib\Channel. If you're not using the bundle, these are the ~300 lines you reimplement.
  • The php-amqplib AMQPStreamConnection API — this is what you actually program against.

First use case (framework-agnostic): publish a JSON message to a direct exchange from a Laravel service, and consume it in an Artisan command. Declare the exchange/queue/binding once at boot (idempotent), then publish with content_type: application/json and an explicit delivery_mode = 2.

Implementation Patterns

Producer as a singleton service. Open one connection/channel per process and reuse it. Publish through a small adapter (e.g. App\Messaging\Publisher) so producers are swappable and testable. Always set content_type and delivery_mode (persistent) explicitly.

Multiple-host connections (new in v1.15.1). The bundle now lets a single connection definition hold a list of hosts. If you mirror that in Laravel config, keep the same idea: pass an array of host/port entries to AMQPStreamConnection (php-amqplib already accepts an array and rotates/fails over at connect time) and don't cache the choice — let the client pick. This buys resilience against a broker node being down at connect time; it does not give you mid-operation failover.

$connection = new AMQPStreamConnection(
    ['rabbitmq-1', 'rabbitmq-2', 'rabbitmq-3'], // multiple hosts
    5672, $user, $pass, $vhost
);

Consumer as an Artisan command. The canonical loop:

$channel->basic_qos(0, 10, false);            // prefetch
$channel->basic_consume($queue, '', false, false, false, false, $handler);
while ($channel->is_consuming()) {
    $channel->wait();                          // blocks; exits on signal or channel error
}

Wrap the handler with try/catch and choose ack (success), nack+requeue (transient), or nack→DLX (poison message). Run under Supervisor/systemd with --max-messages or a max-lifetime so memory doesn't grow unbounded.

Topology as code. Declare exchange_declare, queue_declare, queue_bind on startup, with identical arguments everywhere. Use passive checks or a migration command for production; declare in a dedicated rabbitmq:setup Artisan command rather than on every publish.

Work queue vs pub/sub.

  • Competing consumers: single direct/default exchange, multiple worker processes on one durable queue.
  • Fanout pub/sub: one fanout exchange, per-service queues each bound to it — each service gets its own copy.
  • Routing: topic exchange with order.*.created style keys for selective consumption.

Retries / delays. Either (a) per-queue x-dead-letter-exchange + x-message-ttl retry queues, or (b) the rabbitmq_delayed_message_exchange plugin with an x-delayed-type exchange. Keep retry count in a header, not the payload.

RPC / request-reply. Set reply_to and correlation_id; consumer replies to the callback queue. Rarely worth it — prefer async events, but it's a real pattern when you need a synchronous response.

Bridging to Laravel. Publish from domain events (Event::listen) or model observers, not from controllers. Consume into jobs or directly into service classes. Keep the AMQP layer at the boundary; don't leak AMQPMessage into your domain.

Testing. Point at a disposable broker (Testcontainers / Docker) or a local RabbitMQ in CI. Unit-test the handler in isolation by calling it with a fake AMQPMessage and asserting ack/nack calls on a mocked channel.

Gotchas and Tips

  • Maintenance risk is still the headline, but the picture shifted slightly. v1.15.1 (multiple hosts + a service-definition classname fix in rabbitmq.xml) shows there is some activity, but nothing here changes the fundamentals: it remains a Symfony bundle with a tiny user base, and the feature set you consume is narrow. Pin the version, vendor/fork if you depend on it, and keep the migration-to-raw-php-amqplib path open — the API surface you actually use is small.
  • Multiple hosts ≠ HA. v1.15.1 gives connect-time failover, not automatic reconnect or channel recovery after a broker restart. You still own reconnection logic: catch AMQPConnectionClosedException / AMQPIOException, back off, reconnect, and re-declare topology.
  • The rabbitmq.xml classname fix is a reminder that Symfony service wiring changes can silently break bundle instantiation. If you vendor this bundle, add a smoke test that boots the container and asserts the producer/consumer services resolve — that's exactly the class of bug this release fixes.
  • It is not a Laravel package. No service provider, no config publish, no auto-registration. You'd instantiate and wire everything manually, at which point the bundle buys you little over php-amqplib.
  • php-amqplib is blocking. $channel->wait() blocks; heartbeats and read_write_timeout must be configured together. A too-short read_write_timeout with a long-lived idle connection causes "connection reset by peer" loops.
  • PRECONDITION_FAILED on declare means the existing queue/exchange has different arguments (durable, auto_delete, x-message-ttl, x-dead-letter-exchange) than your declaration. Make declarations match production before touching them, or use passive mode.
  • Prefetch is per-channel, not per-consumer. Too-high prefetch starves other consumers and inflates redelivery on crash. Start low (10–50) and measure.
  • Ack after processing, never before. Unacked messages redeliver on worker crash, so handlers must be idempotent (dedupe by message id / business key).
  • Connections and channels are not thread-safe. One connection per process, one channel per thread/coroutine. Don't share a Producer across Octane workers naively — reset per request/worker.
  • Memory growth in long-running consumers. The PHP process holds onto message payloads; restart workers on a max-message or time budget.
  • Graceful shutdown. Catch SIGTERM/SIGINT, set a flag, let the in-flight message finish and ack, then close the channel. Otherwise you get spurious redeliveries and duplicate side effects on deploy.
  • Serialization drift. If producers set application/json and a consumer expects serialized PHP (or vice versa), you'll get silent garbage. Standardize on JSON + UTF-8 and validate the envelope on consume.
  • Delayed messages need a plugin or a DLX+TTL chain. There is no native per-message delay; don't assume x-message-ttl on a normal queue gives you scheduled delivery.
  • Debugging tooling. Enable the management plugin; use rabbitmqctl list_queues name messages_ready messages_unacknowledged consumers, the management UI for bindings, and rabbitmq_tracing when routing keys vanish. Most "message lost" bugs are unbound queues or a mismatched routing key.
  • Config quirks (Symfony schema). heartbeat, connection_timeout, read_write_timeout, channel_rpc_timeout live under connection options; consumers carry separate qos settings; producers carry exchange + routing key. With v1.15.1 the host entry can now be a list — check how your config layer normalizes it before assuming a single host string. If you translate this to Laravel config, keep the same nesting or you'll misplace timeouts.
  • Lazy/quorum queues require explicit x-queue-type arguments and (for quorum) durable queues — they will not work with auto_delete or exclusive consumers. Decide topology up front; converting a live queue is a drain-and-recreate.
  • Extension points are few. The bundle's useful seams are the connection factory class and per-consumer callbacks. If you need middleware, hooks, metrics, or multi-host strategy control, add them in your own consumer loop — not via the bundle.
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.
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
noith/settings