Mastering Server‑Sent Events (SSE) in PHP and JavaScript: Real‑Time Push Made Simple
This guide explains what Server‑Sent Events (SSE) are, why they are needed for real‑time server‑to‑client communication, presents complete PHP and JavaScript examples, compares three implementation patterns, and contrasts SSE with WebSocket, highlighting strengths and limitations.
Introduction
SSE (Server‑Sent Events) is an HTTP‑based, one‑way (half‑duplex) communication mechanism that lets a server push real‑time data to a client without the client repeatedly polling.
Data Communication
Problem Solved
Traditional HTTP request‑response cannot initiate data from the server; SSE fills this gap.
Typical Use Cases
Real‑time subscription updates
Instant notifications
Live log monitoring
Real‑time statistics
Simple text data transmission
Server‑Side Example (PHP)
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
while (@ob_end_flush()) {}
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');
function sse($data) {
return "data:{$data}
";
}
ob_start();
while (true) {
$json = json_encode(['data' => ['time' => date('Y-m-d H:i:s')]], JSON_UNESCAPED_UNICODE);
echo sse($json);
ob_flush();
flush();
sleep(1);
}Client‑Side Example (JavaScript)
<!doctype html>
<html>
<head><meta charset="UTF-8"><title>Document</title></head>
<body>
<script>
if (!!window.EventSource) {
var sse = new EventSource('http://127.0.0.1/test/sse.php');
sse.onmessage = function(event) {
var response = JSON.parse(event.data);
console.log(response.data.time);
};
sse.onopen = function() { console.log('连接成功'); };
sse.onclose = function() { console.log('连接关闭'); };
sse.onerror = function() { console.error('连接失败'); };
} else {
alert('您的浏览器不支持SSE');
}
</script>
</body>
</html>Synchronization Strategies
Solution 1 – Pure Polling
Method: continuously query the database.
Pros: simple to implement.
Cons: high performance cost, not elegant.
Scenario: small data volume or temporary fix.
ob_start();
$user_id = 1; // example user ID
while (true) {
$notice_count = DB::table('notice')->where('user_id', $user_id)->count();
echo sse(json_encode(['notice_num' => $notice_count]));
ob_flush();
flush();
sleep(1);
}Solution 2 – Event‑Driven Pub/Sub with Message Queue (Redis)
Method: publish a task to a Redis queue when data changes; SSE module consumes the queue.
Pros: avoids intensive polling.
Cons: still consumes resources, slightly more complex.
Scenario: when the subscriber needs to perform richer business logic.
// Publisher
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$user_id = 1;
$redis->lPush('add_one_notice_task:' . $user_id, 1);
// Subscriber
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$user_id = 1;
$notice_count = DB::table('notice')->where('user_id', $user_id)->count();
$redis->set('user_notice_num:' . $user_id, $notice_count);
while (true) {
$task = $redis->rPop('add_one_notice_task:' . $user_id);
if ($task) { $redis->incr('user_notice_num:' . $user_id); }
echo sse(json_encode(['notice_num' => $redis->get('user_notice_num:' . $user_id) ?? 0]));
ob_flush();
flush();
sleep(1);
}Solution 3 – Event‑Driven Polling via Cache
Method: after data changes, write the new value to a cache; the listener repeatedly reads the cache.
Pros: simpler than full pub/sub while avoiding heavy DB polling.
Cons: still a polling loop, consumes some resources.
Scenario: simple data return without complex subscriber logic.
// Trigger side
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$user_id = 1;
$notice_count = DB::table('notice')->where('user_id', $user_id)->count();
$redis->set('user_notice_num:' . $user_id, $notice_count);
// Listener side
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
while (true) {
echo sse(json_encode(['notice_num' => $redis->get('user_notice_num:' . $user_id) ?? 0]));
ob_flush();
flush();
sleep(1);
}Project‑Level Helper Function
function sse($callback, $millisecond = 1000) {
set_time_limit(0);
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
while (@ob_end_flush()) {}
header('Content-Type: text/event-stream; Charset=UTF-8');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
ob_start();
while (true) {
$res = $callback();
if ($res !== null) {
$data = json_encode($res, JSON_UNESCAPED_UNICODE);
echo "data:{$data}
";
}
ob_flush();
flush();
usleep($millisecond * 1000);
}
}
// Usage example
sse(function() {
if ('业务逻辑数据存在') {
return ['k' => 'v'];
}
return null;
}, 1000);Advantages of SSE
Simple to implement and use.
Built‑in reconnection logic handles network interruptions.
Reduces request volume compared to short‑polling and avoids the overhead of adding a full WebSocket layer for lightweight real‑time needs.
Disadvantages of SSE
Not supported by Internet Explorer.
Half‑duplex only; data flows from server to client.
Browsers may limit the number of concurrent SSE connections per domain or per instance.
SSE vs. WebSocket
Protocol Difference
SSE runs over HTTP, while WebSocket uses a separate protocol, though both can maintain persistent connections.
Data Format
SSE transmits plain text (commonly JSON), suitable for simple messages; WebSocket can handle both text and binary, making it better for large media streams.
Communication Mode
SSE is half‑duplex (server‑to‑client only); WebSocket is full‑duplex, allowing bidirectional data exchange.
Compatibility
WebSocket is supported from IE10 onward; SSE is unsupported in all IE versions and varies across other browsers, though polyfills can mitigate gaps.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
