PHP SDK guide

Signals, queries & updates

Choose a message by its consistency contract—fire-and-record signals, read-only queries, or tracked updates that return an applied result.

Choose the message contract

Message Durable effect Caller waits for Handler context
Signal Appended to workflow history Admission Workflow replay consumes signals()
Query No history mutation Read result Query handler reads committed history
Update Accepted and applied as tracked history Accepted or completed Update handler reads committed history

Declare and consume a signal

Declaration advertises the signal name and argument shape. The signature callback is reflected for registration metadata and is never invoked:

$worker->declareSignal(
    'orders.process',
    'approve',
    static fn (string $reviewer): mixed => null,
);

Workflow replay reads the committed signal arguments:

foreach ($context->signals('approve') as [$reviewer]) {
    $approvedBy = $reviewer;
}

Send it through a workflow handle:

$client->workflowHandle('order-1001')->signal('approve', ['Ada']);

Signals are appropriate when the caller only needs acknowledgement that the runtime accepted the event.

Register a read-only query

$worker->registerQuery(
    'orders.process',
    'status',
    static function (QueryContext $context): array {
        return [
            'workflow_id' => $context->workflowId,
            'activities_completed' => count($context->events('ActivityCompleted')),
        ];
    },
);

$status = $handle->query('status');

A query observes committed history. It must not perform an activity or mutate workflow state.

Apply a tracked update

$worker->registerUpdate(
    'orders.process',
    'change-address',
    static fn (QueryContext $context, array $address): array => [
        'accepted' => true,
        'address' => $address,
    ],
);

$result = $handle->update(
    'change-address',
    [['city' => 'London']],
    waitFor: 'completed',
    requestId: 'order-1001-address-v2',
);

Reuse a stable request ID when a caller may retry the same update after losing its response. Use waitFor: 'accepted' when another process will observe completion later.

Follow run transitions deliberately

Ordinary handle methods target the current run. signalSelectedRun(), querySelectedRun(), and updateSelectedRun() preserve the selected run guard. Choose selected-run methods for administrative tools whose answer must refer to one immutable run.

Message names are public contracts

Version a message shape additively. Keep old workers able to decode histories that were already admitted.