Skip to content

Examples

These examples show the intended application-level API. Controllers, models, services, and workers publish events without touching Redis directly.

User notification

Publish from any PHP process:

use App\Sse\Channels\UserNotificationsChannel;
use Maniaba\CodeIgniterSse\Contracts\PublishableEventInterface;
use Maniaba\CodeIgniterSse\Support\Channel;

final readonly class OrderPaidNotification implements PublishableEventInterface
{
    public function __construct(
        private int $userId,
        private int $orderId,
    ) {
    }

    public function channel(): Channel
    {
        return UserNotificationsChannel::forUser($this->userId);
    }

    public function event(): string
    {
        return 'notification.created';
    }

    public function data(): array
    {
        return [
            'title'   => 'Order paid',
            'orderId' => $this->orderId,
        ];
    }
}

sse()->publish(
    new OrderPaidNotification($userId, 918),
);

Listen in the browser:

import {
    RedisSseAdapter,
    SseClient,
} from '/vendor/codeigniter4-sse/sse-client.js';

const live = new SseClient({
    endpoint: '/sse',
    adapter: new RedisSseAdapter(),
    channels: [`users.${currentUserId}.notifications`],
});

live.on('notification.created', ({ data }) => {
    showToast(data.title);
    refreshOrder(data.orderId);
});

live.connect();

Order status

Publish a domain event:

sse()->publish(
    'orders.918',
    'order.updated',
    [
        'orderId' => 918,
        'status'  => 'paid',
    ],
);

Update the visible row:

live.on('order.updated', ({ data }) => {
    document.querySelector(`[data-order="${data.orderId}"] [data-status]`)
        .textContent = data.status;
});

Dashboard refresh

Publish a tenant dashboard metric:

sse()->publish(
    "tenants.{$tenantId}.dashboard",
    'dashboard.metric.changed',
    [
        'metric' => 'openOrders',
        'value'  => 12,
    ],
);

Apply it on the dashboard:

live.on('dashboard.metric.changed', ({ data }) => {
    document.querySelector(`[data-metric="${data.metric}"]`)
        .textContent = data.value;
});

Optional UI patch

For generic internal screens, the application may choose to send a small UI patch event:

sse()->publish(
    'orders.918',
    'ui.patch',
    [
        'target'    => '#order-918-status',
        'operation' => 'text',
        'value'     => 'Paid',
    ],
);

This pattern is intentionally not the primary package API because it couples the backend to page markup.