Installation
Requirements
Before installing the package, verify:
- PHP 8.2 or newer;
- the PHP JSON extension;
- CodeIgniter 4.7 or newer;
- Redis for the Redis adapter, or a Mercure Hub for the Mercure adapter;
- Composer package discovery enabled in the application.
The Redis adapter speaks RESP2 over PHP stream sockets. No PhpRedis extension or third-party Redis client is needed.
The Mercure publisher uses CodeIgniter's CURLRequest client and therefore
requires ext-curl. See Mercure Hub when using that adapter.
Install with Composer
composer require maniaba/codeigniter4-sse
CodeIgniter discovers the package namespace, services, routes, and Spark commands through Composer.
Publish the application config and browser module:
php spark sse:install
The command creates:
app/Config/Sse.php
public/vendor/codeigniter4-sse/sse-client.js
public/vendor/codeigniter4-sse/sse-client.d.ts
public/vendor/codeigniter4-sse/adapters/*.js
public/vendor/codeigniter4-sse/adapters/*.d.ts
Existing files are skipped. Use --force only when they should be replaced,
or --no-assets to publish only the PHP config:
php spark sse:install --no-assets
If the application has disabled Composer discovery in Config\Modules, enable
it before using the automatic package integration:
public $discoverInComposer = true;
Applications using Config\Modules::$composerPackages['only'] must include the
Composer package name:
public $composerPackages = [
'only' => [
'maniaba/codeigniter4-sse',
],
];
Run the following commands to confirm discovery:
php spark routes
php spark list
The route list should contain the SSE endpoint, and the command list should
contain sse:health-check.
Configure Redis
For local development:
public string $channelPrefix = 'app:sse:';
public array $redis = [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
];
Then check connectivity:
redis-cli ping
php spark sse:health-check
The health check validates the package configuration and opens a Redis connection without starting an HTTP stream.
Redis Pub/Sub channels are not isolated by selected database. Always use a
distinct channelPrefix for each application and test suite.
Configure Mercure
Mercure is an alternative to Redis plus the PHP stream endpoint. It keeps
sse()->publish(...), but browsers hold their EventSource connection directly
against the Hub:
public string $broker = 'mercure';
Configure Hub URLs, publisher/subscriber keys, topic prefix, and cookie attributes before publishing. The complete development and production setup is documented under Mercure Hub.
Install the browser client
Applications with a frontend build can install the browser client from npm:
npm install @maniaba/codeigniter4-sse-browser
Then import it from the package:
import { SseClient } from '@maniaba/codeigniter4-sse-browser';
The package includes TypeScript declarations.
Without npm, the installer publishes the source ES module from:
vendor/maniaba/codeigniter4-sse/resources/js/sse-client.js
vendor/maniaba/codeigniter4-sse/resources/js/adapters/
The default public import is:
import { SseClient } from '/vendor/codeigniter4-sse/sse-client.js';
Alternatively, copy the source into an existing asset pipeline:
cp vendor/maniaba/codeigniter4-sse/resources/js/sse-client.js \
public/assets/sse-client.js
cp vendor/maniaba/codeigniter4-sse/resources/js/sse-client.d.ts \
public/assets/sse-client.d.ts
cp -R vendor/maniaba/codeigniter4-sse/resources/js/adapters \
public/assets/adapters
Then import it:
import { SseClient } from '/assets/sse-client.js';
Do not serve the entire vendor/ directory from the web root.
Verify the HTTP stream
The default authorizer permits public.* channels, so a public channel is
useful for the first smoke test:
curl -N \
-H 'Accept: text/event-stream' \
'http://localhost:8080/sse?channels=public.demo'
In a second terminal, publish a test event from application code or a small Spark command:
sse()->publish(
'public.demo',
'demo.updated',
['ready' => true],
);
curl should receive an SSE frame without waiting for the connection to end.
Production checklist
Before exposing the endpoint:
- implement private-channel authorization;
- configure the authenticated user resolver;
- apply application authentication plus reconnect rate/concurrency filters to private stream routes;
- use TLS for remote Redis connections;
- set an application-specific Redis channel prefix;
- disable proxy and FastCGI buffering for the SSE route;
- size PHP-FPM for the expected number of concurrent streams;
- keep finite connection lifetime and heartbeats enabled.