CodeIgniter SSE is a lightweight, powerful Server-Sent Events library for CodeIgniter 4. It provides a clean, framework-native API for building real-time features with one-way event streams over HTTP.
Use it for notifications, progress updates, activity feeds, logs, live dashboards, and other event-driven UI updates. Application code publishes semantic events through one CI4 service, while the selected broker adapter handles Redis or Mercure delivery, browser streaming, and reconnect behavior.
┌─ Redis Pub/Sub ── PHP SSE response ─┐
CodeIgniter application ┤ ├─ Browser
sse()->publish() └─ Mercure Hub ──────────────────────┘
The public API stays independent of the transport. Start with Redis for simple
deployments, switch to Mercure when long-lived browser connections should move
out of PHP, and keep the same sse()->publish(...) application code.
- PHP 8.2 or newer
- CodeIgniter 4.7 or newer
- Redis server for the Redis adapter, or a Mercure Hub
ext-curlwhen using Mercure
Install the package:
composer require maniaba/codeigniter4-sse
php spark sse:installEnsure that Redis is reachable:
redis-cli ping
php spark sse:health-checkThe package speaks RESP2 over PHP stream sockets. It does not require PhpRedis, Predis, or another Redis client package. The PHP JSON extension is required.
Package routes, services, and Spark commands are discovered through CodeIgniter's Composer package discovery. See Installation when discovery is restricted in your application.
Publish an event from a controller, domain service, listener, command, or queue worker:
sse()->publish(
"users.{$userId}",
'notification.created',
[
'title' => 'Order paid',
'orderId' => 918,
],
);Open the stream for one or more logical channels:
GET /sse?channels=users.42,orders.918
Accept: text/event-streamUse the included framework-independent ES module:
import {
RedisSseAdapter,
SseClient,
} from '/vendor/codeigniter4-sse/sse-client.js';
const live = new SseClient({
endpoint: '/sse',
adapter: new RedisSseAdapter(),
channels: [`users.${currentUserId}`],
withCredentials: true,
});
live.on('notification.created', ({ data }) => {
showToast(data.title);
refreshOrder(data.orderId);
});
live.on('status', ({ status }) => {
document.documentElement.dataset.liveStatus = status;
});
live.connect();SseClient opens EventSource through the selected frontend adapter. When the
server broker changes, update the adapter class in the browser client.
The browser's native EventSource automatically reconnects when a connection
ends. With Redis, the package intentionally limits the PHP stream lifetime.
With Mercure, the browser streams directly from the Hub.
The built-in authorization policy permits only channels under public.*.
Every user, tenant, order, project, or other private channel is denied until
the application provides a ChannelAuthorizerInterface implementation.
namespace App\Sse;
use Maniaba\CodeIgniterSse\Contracts\ChannelAuthorizerInterface;
final class ChannelAuthorizer implements ChannelAuthorizerInterface
{
public function authorize(?object $user, string $channel): bool
{
if (str_starts_with($channel, 'public.')) {
return true;
}
if (
$user !== null
&& preg_match('/^users\.(\d+)$/', $channel, $matches) === 1
) {
return (string) $user->id === $matches[1];
}
return false;
}
}Register a matching UserResolverInterface when the application uses session,
Shield, JWT, or another authentication system. Channel names supplied by the
browser are logical names; clients never receive or control the internal Redis
prefix. In production, private SSE routes should also use application
authentication and per-user rate/concurrency filters to control open streams
and reconnect churn; filters do not replace per-channel authorization.
See Channels and authorization for the complete setup.
Create app/Config/Sse.php when defaults need to be changed:
<?php
declare(strict_types=1);
namespace Config;
use Maniaba\CodeIgniterSse\Config\Sse as BaseSse;
final class Sse extends BaseSse
{
public string $channelPrefix = 'myapp:sse:';
public int $heartbeatInterval = 15;
public int $maxConnectionSeconds = 300;
public int $maxChannelsPerConnection = 20;
}Redis connection details and scalar package options can be supplied through
.env. The exact options and production recommendations are documented under
Configuration.
Redis is the default broker and the easiest starting point. It uses Redis
Pub/Sub while CodeIgniter holds the browser's SSE response open from /sse.
For larger environments or applications with many concurrent users, prefer
Mercure: PHP handles short authorization and publish requests, while the Hub
owns the long-lived browser connections.
The first release deliberately uses raw Redis Pub/Sub:
- events are broadcast live;
- disconnected clients do not receive past events;
- there is no replay or guaranteed delivery;
- publisher and subscriber use separate Redis connections;
- event envelopes include an ID and schema version for future adapters.
Use a database, queue, or a future durable broker adapter when an event must
not be lost. Redis Streams and Last-Event-ID replay are outside the Pub/Sub
contract. Redis Pub/Sub is not isolated by numbered Redis databases, so every
application must use its own channelPrefix.
Mercure is available when long-lived streams should not occupy PHP workers:
public string $broker = 'mercure';Publishing remains unchanged. The /sse route becomes a short channel
authorization request that sets a topic-scoped HttpOnly JWT cookie, and the
browser client connects directly to the Hub:
import {
MercureSseAdapter,
SseClient,
} from '/vendor/codeigniter4-sse/sse-client.js';
const live = new SseClient({
endpoint: '/sse',
adapter: new MercureSseAdapter(),
channels: [`users.${currentUserId}`],
});Use the frontend adapter that matches the configured broker. Mercure's adapter authorizes through the package route and then opens EventSource on the Hub.
Mercure can replay retained Hub history through Last-Event-ID. See
Mercure Hub for Docker, signing keys, authorization,
cookies, CORS, and reverse-proxy configuration.
- Installation
- Quick start
- Configuration
- Architecture
- Channels and authorization
- Browser client
- Mercure Hub
- Streaming and deployment
- Testing
- Troubleshooting
composer ciRedis integration tests require a reachable test Redis instance and use a dedicated prefix. See Testing.
CodeIgniter SSE is released under the MIT License. CodeIgniter-derived portions retain their notices in Third-party notices.