rabbit-converter/rabbit-php
A PHP client for the Rabbit Converter API that lets Laravel and plain PHP apps convert documents between formats like PDF, DOCX, and HTML through a simple, fluent interface.
rabbit-converter/rabbit-php is a small, MIT-licensed PHP package for working with RabbitMQ. Treat it as a thin client/consumer toolkit rather than a full Laravel queue driver: you get connection handling and message publishing/consumption, and you supply the application-level conventions (message contracts, retries, observability, worker supervision).
Start by verifying the package's runtime assumptions before writing code:
composer.json in the repository or after install. Determine whether it uses php-amqplib/php-amqplib (pure PHP) or ext-amqp. That decides your Docker image and whether you need a PHP extension.composer require rabbit-converter/rabbit-php
Pin a known-good version ("rabbit-converter/rabbit-php": "x.y.*") rather than floating ^ constraints; with a package this small, upstream churn is a real risk.config/app.php. If there is a publishable config:
php artisan vendor:publish --tag=rabbit-config
5672), user, password, and vhost (/):
RABBIT_HOST=127.0.0.1
RABBIT_PORT=5672
RABBIT_USER=guest
RABBIT_PASSWORD=guest
RABBIT_VHOST=/
vendor/rabbit-converter/rabbit-php/src for the connection factory, publisher, and consumer base classes. Check for an examples/ directory and the test suite — the tests usually reveal the intended lifecycle (connect → declare topology → publish/consume → ack) faster than the docs.The first useful end-to-end use case is a fire-and-forget job: a controller publishes a small JSON payload to a queue, and a CLI worker consumes it and calls an application service. Keep that path working before adding retries, dead-letter queues, or multiple connections.
// app/Http/Controllers/RegisterController.php
public function store(RegisterRequest $request)
{
$user = User::create($request->validated());
// Publisher is injected; payload is a plain array/JSON string.
$this->publisher->publish('user.registered', [
'id' => $user->id,
'email' => $user->email,
'occurred_at'=> now()->toIso8601String(),
]);
return redirect()->route('dashboard');
}
// app/Console/Commands/ConsumeUserEvents.php — shape of a worker loop
public function handle(): int
{
$this->consumer->consume('user.registered', function (string $body, $delivery) {
$payload = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
app(SendWelcomeEmail::class)($payload['id']);
// Acknowledge only after the handler succeeds.
$this->consumer->ack($delivery);
});
return self::SUCCESS;
}
The exact method names depend on the version you install; confirm them in src/ before copying snippets into production.
Keep publishing behind an application service. Do not let controllers or models call the package client directly. Wrap it in something like App\Messaging\EventPublisher with a small interface (publish(string $routingKey, array $payload): void). That gives you one place to add message IDs, timestamps, versioning, and logging, and one seam to fake in tests.
Define an envelope contract early. Standardize on JSON with a stable shape:
{
"id": "uuid",
"type": "user.registered",
"version": 1,
"occurred_at": "2025-01-01T00:00:00Z",
"payload": { "...": "..." }
}
Consumers should validate type and version and reject unknown versions explicitly (ack + log) rather than crashing repeatedly.
One consumer per queue, handlers as invokable classes. Keep the consume loop dumb: deserialize, dispatch to SendWelcomeEmail, GenerateThumbnail, etc., ack/nack. This makes handlers unit-testable without RabbitMQ:
$handler = new SendWelcomeEmail($mailer);
$handler(['id' => $user->id]);
Use Laravel's container for wiring. Bind the package's connection/client as a singleton in a service provider. Do not resolve a new connection per request if you can reuse one within a worker; connections and channels are relatively expensive and long-lived.
Topology as code. Declare exchanges, queues, and bindings in one place (a command or bootstrap step), not ad hoc inside handlers. For retries, the reliable pattern is a dead-letter exchange: main queue → DLX on failure → retry queue with TTL → back to main queue. Avoid busy-loop requeueing with nack(requeue: true).
Ack semantics. Ack after the handler completes, never before. On exception, distinguish between transient failures (requeue or route to retry) and poison messages (ack/nack without requeue and route to a dead-letter queue). Log the delivery tag and message ID so you can correlate.
Multiple connections. If the package supports named connections, use a default one for web publishing and a separate one for workers. This keeps prefetch/QoS settings and heartbeat tuning isolated.
Local development. Run RabbitMQ in docker-compose with the management image (rabbitmq:3-management) and check the UI on :15672. Use a project-specific vhost so local queues do not collide with shared environments.
Testing. Unit-test handlers directly. For integration tests, publish to a throwaway queue and consume with a timeout; assert on the handler side effect, not on broker internals. If the package exposes a fake/in-memory transport, use it for feature tests; otherwise isolate the publisher behind your own interface and use a recording fake.
Observability. Log at publish (message id, type) and at consume (message id, duration, outcome). Emit metrics for queue depth, consume rate, failures, and handler latency. These are the first things you will want when a queue backs up.
Queue::push() and Horizon visibility, verify that explicitly. If it is a standalone client, Laravel's queue:work, failed-jobs table, and Horizon will not manage it. You will need your own supervisor config and restart strategy.DB::reconnect() periodically, unset large payloads, and recycle the worker after N messages. Use Supervisor with stopwaitsecs and restart workers on deploy.basic_qos so one worker does not pull thousands of messages into memory. Start with 10–50 and tune against handler latency.php-amqplib-based clients do not always reconnect transparently after broker restarts. Wrap consume loops with reconnect/backoff logic and let Supervisor restart crashed workers.php artisan config:cache (or clear it). A stale cached config is a common "why is it connecting to the wrong host" cause.id or a business key. Duplicates will happen.How can I help you explore Laravel packages today?