php 52 lines · 9 steps

Server-Sent Events in Laravel

A controller streams live notifications to the browser over a long-lived HTTP connection using Server-Sent Events.

Explained by highlit
1<?php
2 
3namespace App\Http\Controllers;
4 
5use Illuminate\Http\Request;
6use Symfony\Component\HttpFoundation\StreamedResponse;
7 
8class EventStreamController extends Controller
9{
10 public function stream(Request $request): StreamedResponse
11 {
12 $response = new StreamedResponse(function () use ($request) {
13 $lastId = (int) $request->header('Last-Event-ID', 0);
14 
15 while (! connection_aborted()) {
16 $events = Notification::query()
17 ->where('id', '>', $lastId)
18 ->orderBy('id')
19 ->limit(20)
20 ->get();
21 
22 foreach ($events as $event) {
23 $lastId = $event->id;
24 
25 echo 'id: ' . $event->id . "\n";
26 echo 'event: ' . $event->type . "\n";
27 echo 'data: ' . json_encode([
28 'title' => $event->title,
29 'body' => $event->body,
30 'at' => $event->created_at->toIso8601String(),
31 ]) . "\n\n";
32 }
33 
34 echo ": heartbeat\n\n";
35 
36 if (ob_get_level() > 0) {
37 ob_flush();
38 }
39 flush();
40 
41 sleep(3);
42 }
43 });
44 
45 $response->headers->set('Content-Type', 'text/event-stream');
46 $response->headers->set('Cache-Control', 'no-cache');
47 $response->headers->set('Connection', 'keep-alive');
48 $response->headers->set('X-Accel-Buffering', 'no');
49 
50 return $response;
51 }
52}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Server-Sent Events keep one HTTP connection open and push newline-delimited text frames instead of polling repeatedly.
  2. 2Tracking a last-seen id lets the stream resume exactly where the client left off after a reconnect.
  3. 3Explicit output flushing and buffering-disabled headers are essential to actually deliver events as they happen.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Server-Sent Events in Laravel — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code