Producing messages with the PHP core
Last updated:
Producing is two steps: build the canonical envelope, then encode it to JSON and publish the bytes with your broker client.
From a typed job
Implement BabelQueue\Contracts\PolyglotJob — a URN plus a pure-array payload:
use BabelQueue\Contracts\PolyglotJob;
final class OrderCreated implements PolyglotJob
{
public function __construct(public int $orderId) {}
public function getBabelUrn(): string
{
return 'urn:babel:orders:created';
}
public function toPayload(): array
{
return ['order_id' => $this->orderId];
}
}
use BabelQueue\Codec\EnvelopeCodec;
$envelope = EnvelopeCodec::fromJob(new OrderCreated(1042), 'orders');
$json = EnvelopeCodec::encode($envelope);
// publish $json onto the "orders" queue with your transport (below)
From a raw URN + data
When you don’t have a job object, build it directly:
$envelope = EnvelopeCodec::make('urn:babel:orders:created', ['order_id' => 1042], 'orders');
$json = EnvelopeCodec::encode($envelope);
make(string $urn, array $data = [], string $queue = 'default', ?string $traceId = null, array $meta = [])
returns the envelope as a plain PHP array. A fresh trace_id (v4 UUID) is stamped
automatically; pass $traceId to continue an existing trace, or implement
BabelQueue\Contracts\HasTraceId on your job.
Publish
encode() produces the exact UTF-8 JSON bytes every other SDK reads — see
Transports for the reference Redis/RabbitMQ
publishers, or move the string with any broker client you already use.
{
"job": "urn:babel:orders:created",
"trace_id": "…",
"data": { "order_id": 1042 },
"meta": { "id": "…", "queue": "orders", "lang": "php", "schema_version": 1, "created_at": 1749132727000 },
"attempts": 0
}
Extension (meta) keys
make() takes an optional meta: array for your own meta entries:
$envelope = EnvelopeCodec::make(
'urn:acme:orders:created',
['order_id' => 1042],
'orders',
meta: ['ext' => ['acme' => ['tier' => 'gold']]],
);
A key that collides with a core meta key (id, queue, lang, schema_version, created_at)
or a forbidden one (max_retries, attempts, source, ts) throws
InvalidEnvelopeException. encode() throws the same exception for a forbidden key (timestamp,
urn, meta.max_retries, meta.attempts, meta.source, meta.ts) instead of stripping it.
Keep vendor data under a single meta.ext.<vendor> block and use snake_case keys
(ADR-0031). The entries are written next to the core meta keys and survive every retry,
dead-letter and redrive hop. See Extension keys in the
envelope spec.
Next: Consuming messages.