PHP
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Object-Oriented PHP
-
Section 5: Working with Data
-
Section 6: Modern PHP (PHP 8)
-
Section 7: Working with Files and Networking
-
Section 8: Common PHP Frameworks Overview
-
Section 9: Tooling and Ecosystem
-
Section 10: Practical Projects
-
Section 11: Interview Practice
-
Section 12: More Standard Library
-
Section 13: Data Structures and Algorithms in PHP
-
Section 14: More Practice Exercises
-
Section 15: More Security and Best Practices
-
Section 16: More Testing and Tooling
-
Section 17: WordPress-Style CMS Concepts
-
Section 18: Advanced OOP Practice
-
Section 19: More Web Fundamentals
-
Section 20: Database Practice
-
Section 21: PHP Manual: Array Functions
-
Section 22: PHP Manual: Date and Calendar Functions
-
Section 23: PHP Manual: Filesystem and Directory Functions
-
Section 24: PHP Manual: Filter and Var Handling
-
Section 25: PHP Manual: Math Functions
-
Section 26: PHP Manual: JSON and XML
-
Section 27: PHP Manual: Network and Stream Functions
-
Section 28: PHP Manual: Error and Exception Handling
-
Section 29: PHP Manual: Output Control and Misc
-
Section 30: PHP Manual: FTP, Zip, and Mail
-
Section 31: Modern PHP Frameworks Deep Dive
-
Section 32: PHP Design Patterns
-
Section 33: More Practice Exercises
-
Section 34: PHP Performance and Deployment
-
Section 35: More Interview Practice
-
Section 36: More PHP Standard Library
-
Section 37: PHP Concurrency and Async
-
Section 38: More Web Development Practice
-
Section 39: PHP Testing Deep Dive
-
Section 40: Composer and Package Development
-
Section 41: PHP Security Deep Dive
-
Section 42: More Practical Projects
-
Section 43: Legacy PHP Maintenance
-
Section 44: More Algorithm Practice
-
Section 45: Final Practice and Review
-
Section 46: PHP for E-Commerce Patterns
-
Section 47: PHP API Design Deep Dive
-
Section 48: PHP Caching Strategies
-
Section 49: PHP Queue and Background Jobs
-
Section 50: PHP Multi-Tenancy Patterns
-
Section 51: PHP Real-Time Features
-
Section 52: PHP CMS and Content Modeling
-
Section 53: PHP Internationalization
-
Section 54: More Framework-Specific Practice
-
Section 55: PHP Legacy Code Refactoring
-
Section 56: More Practice Projects Round 2
-
Section 57: PHP Command-Line Applications
-
Section 58: PHP and Microservices
-
Section 59: More Interview and Review Round 2
215: Server-Sent Events in PHP
I see this all the time: a developer wants to push a notification or a live update to the browser and immediately starts hunting for a WebSocket library or wondering if they need to spin up a Node.js sidecar to handle "real-time" traffic. They assume that if you want the server to initiate a conversation with the client, you have to move away from standard HTTP and into the world of persistent socket connections.
The "WebSockets are the only way" Fallacy
The mistake is thinking that bidirectional communication is the only way to achieve "push" functionality. WebSockets are powerful, but they are overkill if your data only flows one way—from the server to the client. When you use WebSockets, you're upgrading the protocol entirely, which often means dealing with load balancer headaches and complex state management on the backend.
If you just need to stream a live feed of data—like a stock ticker, a progress bar for a long-running export, or a server resource monitor—Server-Sent Events (SSE) are a far more elegant choice. SSE operates over standard HTTP. There's no protocol upgrade, no special handshake, and it's natively supported by the EventSource API in the browser. It essentially keeps an HTTP connection open and allows the server to "drip" data to the client whenever it wants.
Using the HTTP Stream to Push Data
To make this work in PHP, you have to tell the browser that this isn't a standard HTML page or a JSON response. You're sending a stream. The magic happens with the text/event-stream MIME type.
Here is how I typically set up a simple resource monitor. Note the use of flush(); without it, PHP will buffer the output and the browser won't see any updates until the script actually ends, which defeats the entire purpose.
<?php
// Prevent the script from timing out
set_time_limit(0);
// Essential headers for SSE
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no'); // Disables buffering on Nginx
while (true) {
// Simulate getting system load or a database update
$load = sys_getloadavg();
$data = [
'cpu' => $load[0],
'timestamp' => date('H:i:s')
];
// SSE format requires "data: " prefix and two newlines at the end
echo "data: " . json_encode($data) . "\n\n";
// Push the data out of the PHP buffer to the browser immediately
if (ob_get_level() > 0) {
ob_flush();
}
flush();
// Wait 2 seconds before the next update
sleep(2);
}
?>
On the frontend, you don't need fetch or axios. You use the EventSource object. I love how clean the JS side is compared to the boilerplate required for WebSockets.
const evtSource = new EventSource("monitor.php");
evtSource.onmessage = function(event) {
const data = JSON.parse(event.data);
console.log(`CPU Load at ${data.timestamp}: ${data.cpu}`);
document.getElementById('cpu-display').innerText = data.cpu;
};
evtSource.onerror = function(err) {
console.error("EventSource failed:", err);
};
One thing to keep in mind: because SSE keeps a connection open, you can quickly run into the maximum execution limit of your PHP process or hit the concurrent connection limit of your web server (especially if you're using Apache with a limited worker pool). If you're building this for a high-traffic site, this is where you'd start looking at an asynchronous engine like Swoole, but for internal tools or low-to-mid traffic apps, standard PHP is plenty.
📋 Practical Task
Build a Real-time System Log Tailer
Your task is to create a PHP-based SSE stream that simulates "tailing" a log file. Instead of reading a real file (which might vary by OS), you will simulate a log file by reading from a simple text file named app.log.
Requirements:
- Create a file called
app.logwith a few lines of dummy text. - Write a PHP script
stream_logs.phpthat:- Sets the correct
text/event-streamheaders. - Enters a
while(true)loop. - Checks the file size of
app.log. If the file has grown since the last check, read the new lines and push them to the browser using thedata: [message]\n\nformat. - Uses
flush()to ensure data is sent immediately. - Sleeps for 1 second between checks to avoid CPU spiking.
- Sets the correct
- Create a simple HTML page with a
<div id="log-window">and a script usingEventSourceto append every new log line received from the server into that div.
Testing your work: Open your HTML page in one tab, and in another tab (or via terminal), append a new line to app.log. You should see the new line appear in your browser instantly without refreshing the page.
There are no comments for now.