webware/sse

A PHP library for Server-Sent Events (SSE) that provides a simple and efficient way to send real-time updates from the server to the client.

Maintainers

Package info

github.com/tyrsson/sse

pkg:composer/webware/sse

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.1.x-dev 2026-03-15 02:16 UTC

This package is auto-updated.

Last update: 2026-03-15 02:16:32 UTC


README

A Server-Sent Events (SSE) component for Mezzio applications built on the Laminas ecosystem.

  • PSR-7 nativeSseResponse extends Laminas\Diactoros\Response
  • EmitterStack-awareSseEmitter implements EmitterInterface and returns false for non-SSE responses, letting SapiEmitter handle the rest
  • PSR-15 ready — abstract handler base class and dual-mode middleware
  • Generator-basedyield events directly from PHP generators for clean, lazy streaming
  • Reconnection supportLast-Event-ID header extracted and forwarded automatically
  • Built-in heartbeat — configurable keep-alive comment frames
  • PSR-11 containerConfigProvider registers services with any PSR-11 container; laminas-servicemanager is optional

Quick Start

1. Install

composer require webware/sse

2. Register the ConfigProvider

// config/config.php
use Laminas\ConfigAggregator\ConfigAggregator;
use Webware\SSE\ConfigProvider;

$aggregator = new ConfigAggregator([
    ConfigProvider::class,
    // your other providers …
]);

3. Push SseEmitter onto the EmitterStack

// public/index.php (or wherever your Mezzio bootstrap lives)
use Laminas\HttpHandlerRunner\Emitter\EmitterStack;
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
use Webware\SSE\SseEmitter;

$stack = new EmitterStack();
$stack->push(new SapiEmitter());                    // handles regular responses
$stack->push($container->get(SseEmitter::class));   // handles SseResponse first

4. Create an event handler

use Generator;
use Psr\Http\Message\ServerRequestInterface;
use Webware\SSE\AbstractSseHandler;
use Webware\SSE\Event;

final class TimeHandler extends AbstractSseHandler
{
    protected function stream(
        ServerRequestInterface $request,
        ?string $lastEventId,
    ): Generator {
        while (true) {
            yield new Event(data: date('H:i:s'), event: 'tick');
            sleep(1);
            yield null; // trigger heartbeat check between real events
        }
    }
}

5. Route it

// config/routes.php
$app->get('/events/time', TimeHandler::class);

6. Subscribe in the browser

<!-- ESM (modern browsers / bundlers) -->
<script type="module">
  import { SseClient } from './js/sse-client.js';

  const client = new SseClient('/events/time', {
    onOpen:  () => console.log('connected'),
    onError: (err) => console.warn('error', err),
  });

  client.on('tick', (time) => console.log('server time:', time));
</script>

<!-- Or via the IIFE global build -->
<script src="js/sse-client.iife.js"></script>
<script>
  const client = new SseClient('/events/time');
  client.on('tick', (time) => console.log('server time:', time));
</script>

Documentation

Topic Description
Installation Requirements, Composer install, optional packages
Configuration ConfigProvider, webware_sse config keys, overriding defaults
Events Event, EventInterface, named events, multi-line data, retry
SseResponse PSR-7 response object, default headers, custom headers
SseEmitter EmitterStack setup, heartbeat, connection abort handling
AbstractSseHandler PSR-15 handler base class, Last-Event-ID, reconnection
SseMiddleware Preprocessor mode, terminal factory mode
Mezzio Integration Full end-to-end guide for Mezzio applications
JavaScript Client Browser / Node SSE client with reconnect, typed events, and polyfill

Requirements

  • PHP 8.2, 8.3, 8.4, or 8.5
  • laminas/laminas-diactoros ^3.0
  • laminas/laminas-httphandlerrunner ^2.0

License

BSD-3-Clause. See LICENSE.