Server Sent Events with CodeIgniter – Push Notifications

Introduction

In this tutorial we will create an example on server sent events (SSE) with CodeIgniter – push notifications. Sometimes we face situations, where the application needs only one way communication, i.e., sending data from server to the client and for this Spring provides a simpler solution using Server Sent Events (SSE).

SSE is a technology that allows you to stream data from server to the browser (Push Notifications) within one HTTP connection in one direction.

For example, pushing stock price changes in real-time or showing progress of long-running process or real time showing of cricket or football scores on display board etc.

Browser Support

SSE are supported in most modern browsers. Only Microsoft’s IE and Edge browsers do not have a built in implementation.

But there is a way out because Server-Sent Events uses common HTTP connections and can therefore be implemented with the following libraries to support IE and Edge browsers.

  • https://github.com/remy/polyfills/blob/master/EventSource.js by Remy Sharp
  • https://github.com/rwldrn/jquery.eventsource by Rick Waldron
  • https://github.com/amvtek/EventSource by AmvTek
  • https://github.com/Yaffle/EventSource by Yaffle

Prerequisites

CodeIgniter 3.1.11, PHP 7.4.3, Apache HTTP Server 2.4

Create Project Directory

It’s assumed that you have setup Apache 2.4, PHP 7.4.3 and Codeigniter 3.1.11 in Windows system.

Now we will create a project root directory called codeIgniter-3.1.11-server-sent-event under the Apache server’s htdocs folder.

Now move all the directories and files from CodeIgniter 3.1.11 framework into codeIgniter-3.1.11-server-sent-event directory.

We may not mention the project root directory in subsequent sections and we will assume that we are talking with respect to the project root directory.

Autoload Configuration

We need some configurations, such as, auto-loading for helpers to avoid loading every time we need to use.

Modify application/config/autoload.php file for auto-loading required helper functions.

This one time auto-loading gives flexibility to uniformly use the helper functions anywhere throughout the application without loading repeatedly.

$autoload['helper'] = array('url');

Controller Class

Create a controller file Welcome.php under application/controllers with the following source code.

The below controller class handles request and response for clients.

The index() function loads the view when home page is shown on the browser.

The event_data() function periodically sends data to the event source. The most of the lines are self-explanatory with the respective comment. The original example can be found at https://github.com/mdn/dom-examples/tree/master/server-sent-events.

In your real life application the source of data could be external source, feed or any other stream of data.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Welcome extends CI_Controller {
	
	public function index() {
		$this->load->view('welcome_message');
	}

	public function event_data() {
		header("Content-Type: text/event-stream");
		header("Cache-Control: no-cache");
		header("Connection: keep-alive");

		$counter = rand(1, 10); // a random counter
		
		while (1) { // 1 is always true, so repeat the while loop forever (aka event-loop)
			$curDate = date(DATE_ISO8601);
			echo "event: ping\n", 'data: {"time": "' . $curDate . '"}', "\n\n";

			// Send a simple message at random intervals.
			$counter--;

			if (!$counter) {
				echo 'data: This is a message at time ' . $curDate, "\n\n";
				$counter = rand(1, 10); // reset random counter
			}

			// flush the output buffer and send echoed messages to the browser
			while(ob_get_level() > 0) {
				ob_end_flush();
			}

			flush();

			// break the loop if the client aborted the connection (closed the page)
			if(connection_aborted()) {
				break;
			}

			// sleep for 1 second before running the loop again
			sleep(1);
		}
    }
	
}

View File

The view file is responsible for displaying information on the web page.

The following source code is written into welcome_message.php under application/views folder. You will find that the ping is written every one second and message is being displayed as and when it is available. You can read more on EventSource at https://developer.mozilla.org/en-US/docs/Web/API/EventSource.

You are given two buttons on the UI so that you can either disconnect from the server or re-establish the connection to the server. Re-establishing the connection will start from the beginning.

Notice in the below EventSource object, we are passing index.php as part of the URL, if you have removed index.php from URL using htaccess file then you don’t need to include index.php in the URL.

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
?><!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Welcome to Server Sent Events (SSE) using CodeIgniter</title>

	<style type="text/css">

	::selection { background-color: #E13300; color: white; }
	::-moz-selection { background-color: #E13300; color: white; }

	body {
		background-color: #fff;
		margin: 40px;
		font: 13px/20px normal Helvetica, Arial, sans-serif;
		color: #4F5155;
	}

	a {
		color: #003399;
		background-color: transparent;
		font-weight: normal;
	}

	h1 {
		color: #444;
		background-color: transparent;
		border-bottom: 1px solid #D0D0D0;
		font-size: 19px;
		font-weight: normal;
		margin: 0 0 14px 0;
		padding: 14px 15px 10px 15px;
	}

	code {
		font-family: Consolas, Monaco, Courier New, Courier, monospace;
		font-size: 12px;
		background-color: #f9f9f9;
		border: 1px solid #D0D0D0;
		color: #002166;
		display: block;
		margin: 14px 0 14px 0;
		padding: 12px 10px 12px 10px;
	}

	#body {
		margin: 0 15px 0 15px;
	}

	p.footer {
		text-align: right;
		font-size: 11px;
		border-top: 1px solid #D0D0D0;
		line-height: 32px;
		padding: 0 10px 0 10px;
		margin: 20px 0 0 0;
	}

	#container {
		margin: 10px;
		border: 1px solid #D0D0D0;
		box-shadow: 0 0 8px #D0D0D0;
	}
	</style>
</head>
<body>

<div id="container">
	<h1>Welcome to Server Sent Events (SSE) using CodeIgniter</h1>

	<div id="body">
		<button id="close">Close the connection</button>
		<button id="open">Refresh the connection</button>
		<ul>
		</ul>
		
		<script>
			var closeButton = document.getElementById('close');
			var openButton = document.getElementById('open');
			
			var evtSource = new EventSource('index.php/welcome/event_data');

			var eventList = document.querySelector('ul');

			evtSource.onopen = function() {
				openButton.disabled = true;
				closeButton.disabled = false;
				console.log("Connection to server opened.");
			};

			evtSource.onmessage = function(e) {
			var newElement = document.createElement("li");

			newElement.textContent = "message: " + e.data;
				eventList.appendChild(newElement);
			};

			evtSource.onerror = function() {
				console.log("EventSource failed.");
			};

			closeButton.onclick = function() {
				evtSource.close();
				openButton.disabled = false;
				closeButton.disabled = true;
				console.log('Connection closed');				
			};
			
			openButton.onclick = function() {
				location.reload();
				openButton.disabled = true;
			};

			evtSource.addEventListener("ping", function(e) {
				var newElement = document.createElement("li");
				var obj = JSON.parse(e.data);
				newElement.innerHTML = "ping at " + obj.time;
				eventList.appendChild(newElement);
			}, false);
		</script>
	</div>
</div>

</body>
</html>

Testing the Application

Once your HTTP server is up and running, you can hit URL http://localhost/codeIgniter-3.1.11-server-sent-event/ in the browser.

Now you will see continuous ping and message are being displayed.

server sent events with codeigniter push notifications

Download

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *