hosmelq/sse
WHATWG-compliant PHP 8.2+ client for consuming Server-Sent Events. Connect via GET/POST using Guzzle, iterate events with a memory-efficient generator, and access data/event/id/retry fields with optional JSON decoding.
Http client or Guzzle, requiring minimal configuration.Event facade, enabling cross-platform consistency (e.g., broadcasting to Pusher or WebSocket clients).Artisan commands or queue workers, fitting Laravel’s CLI-driven workflows.SSEConnectionException, SSEProtocolException) must be mapped to Laravel’s logging (Log::error) and retry mechanisms (e.g., Laravel\Queue\Retryable).Last-Event-ID is critical for reconnecting to streams. Laravel’s session/cookie system may not persist this state; alternatives:
Cache::remember or a dedicated table).Http client supports headers, but persistent auth may need custom interceptors.Http client for consistency:
use Illuminate\Support\Facades\Http;
$client = new \HosmelQ\SSE\Client(Http::client());
ShouldQueue job:
class ProcessSSEEvents implements ShouldQueue
{
public function handle() {
$client = new \HosmelQ\SSE\Client();
foreach ($client->get('https://api.example.com/stream')->events() as $event) {
// Dispatch Laravel events or process data
ProcessEvent::dispatch($event);
}
}
}
Event facade to normalize SSE events:
foreach ($eventSource->events() as $event) {
event(new SSEEvent($event->data, $event->event));
}
Client in Laravel’s DI container for testability:
$this->app->bind(\HosmelQ\SSE\Client::class, fn () => new \HosmelQ\SSE\Client());
Artisan command or tinker:
php artisan make:command ProcessSSEEvents
public function handle() {
$client = new \HosmelQ\SSE\Client();
$eventSource = $client->get('https://api.example.com/stream');
foreach ($eventSource->events() as $event) {
Log::info("Received event: {$event->data}");
}
}
ProcessSSEEvents::dispatch()).$lastEventId = Cache::get('sse_last_event_id', null);
$eventSource = $client->get('https://api.example.com/stream', [
'headers' => ['Last-Event-ID' => $lastEventId]
]);
Laravel Debugbar or Prometheus):
foreach ($eventSource->events() as $event) {
$start = microtime(true);
// Process event
$duration = microtime(true) - $start;
Metrics::record('sse.event_processing', $duration);
}
Laravel Horizon for queue monitoring).Http client:
$client = new \HosmelQ\SSE\Client(Http::withOptions([
'headers' => ['Authorization' => 'Bearer ' . auth()->token()]
])->client());
Client to Laravel’s container for easy mocking in tests.Event::listen(SSEEvent::class, function ($event) {
Notification::send(User::all(), new SSEUpdate($event->data));
});
SSEConnectionException to close connections cleanly:
try {
foreach ($eventSource->events() as $event) { ... }
} catch (SSEConnectionException $e) {
Log::error("SSE connection failed: " . $e->getMessage());
Cache::put('sse_last_event_id', $eventSource->getLastEventId(), now()->addHour());
}
public function test_sse_consumption() {
$this->artisan('ProcessSSEEvents')
->expectsOutput('Received event: {"data": "test"}')
->assertExitCode(0);
}
hosmelq/sse for updates (MIT license allows forks if needed). Subscribe to release notes or set up a GitHub watch.composer.json to avoid unexpected breaking changes:
"require": {
"hosmelq/sse": "^0.1.0"
}
\HosmelQ\SSE\Client.How can I help you explore Laravel packages today?