(02-24-2020, 05:28 PM)dave friend Wrote: I built a CodeIgniter version of the server-sent-events sample. It's modified from the Github example a tiny bit but works as expected.
Controller: Eventsource.php
PHP Code:
<?php
class Eventsource extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->model('eventsource_m');
}
public function index()
{
$this->load->view('eventsource_v');
}
public function sse()
{
$this->eventsource_m->process();
}
}
View: eventsource_v.php
PHP Code:
<html>
<head>
<meta charset="UTF-8">
<title>Server-sent events demo</title>
</head>
<body>
<button>Close the connection</button>
<ul>
</ul>
<script>
var button = document.querySelector('button');
var evtSource = new EventSource(<?= "'".base_url('eventsource/sse', 'https')."'"; ?> );
console.log(evtSource.withCredentials);
console.log(evtSource.readyState);
console.log(evtSource.url);
var eventList = document.querySelector('ul');
evtSource.onopen = function () {
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.");
};
button.onclick = function () {
console.log('Connection closed');
evtSource.close();
};
</script>
</body>
</html>
Model: Eventsource_m.php
PHP Code:
<?php
class Eventsource_m extends CI_Model
{
public function process()
{
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream");
// 1 is always true, so repeat the while loop forever (aka event-loop)
while (1)
{
$curDate = date(DATE_ISO8601);
// Send a simple message at 2 second intervals.
echo 'data: This is a message at time ' . $curDate, "\n\n";
// 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 2 seconds before running the loop again
sleep(2);
}
}
}
Direct the browser to https://your_domain/eventsource and see a new message every two seconds. Clearly the EventSource messages can be sent from a model.
The only tricky bit was in the JavaScript with setting the URL for EventSource.
PHP Code:
var evtSource = new EventSource(<?= "'".base_url('eventsource/sse', 'https')."'"; ?> );
Notice how I had to explicitly concatenate single quotes around the output of base_url(). Without those JavaScript could not properly evaluate the argument. This is a common issue when combining PHP and JavaScript.
Using the browsers JavaScript console is important when trying to figure out what, if any, failures are occurring. I spotted the above issue right away.
Hopefully, all this helps.
It's not clear to me what you want to happen when processing is complete.
Based on your view it looks like you want to send data back to drive a progress-bar. If so, a message value equal to "100" would make for a good signal to disconnect the EventSource and move on to whatever is supposed to happen.
Thank you so much! I'm going to try this soon! I suppose I should have mentioned that my cfa_model makes several requests to a SOAP api in the data conversion. While I'm working on implementing your ideas, would these calls effect what we are trying to do in any way? If so, how do I work around them?
Again, thank you a TON!
(02-24-2020, 05:28 PM)dave friend Wrote: I built a CodeIgniter version of the server-sent-events sample. It's modified from the Github example a tiny bit but works as expected.
Controller: Eventsource.php
PHP Code:
<?php
class Eventsource extends CI_Controller
{
function __construct()
{
parent::__construct();
$this->load->helper('url');
$this->load->model('eventsource_m');
}
public function index()
{
$this->load->view('eventsource_v');
}
public function sse()
{
$this->eventsource_m->process();
}
}
View: eventsource_v.php
PHP Code:
<html>
<head>
<meta charset="UTF-8">
<title>Server-sent events demo</title>
</head>
<body>
<button>Close the connection</button>
<ul>
</ul>
<script>
var button = document.querySelector('button');
var evtSource = new EventSource(<?= "'".base_url('eventsource/sse', 'https')."'"; ?> );
console.log(evtSource.withCredentials);
console.log(evtSource.readyState);
console.log(evtSource.url);
var eventList = document.querySelector('ul');
evtSource.onopen = function () {
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.");
};
button.onclick = function () {
console.log('Connection closed');
evtSource.close();
};
</script>
</body>
</html>
Model: Eventsource_m.php
PHP Code:
<?php
class Eventsource_m extends CI_Model
{
public function process()
{
date_default_timezone_set("America/New_York");
header("Content-Type: text/event-stream");
// 1 is always true, so repeat the while loop forever (aka event-loop)
while (1)
{
$curDate = date(DATE_ISO8601);
// Send a simple message at 2 second intervals.
echo 'data: This is a message at time ' . $curDate, "\n\n";
// 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 2 seconds before running the loop again
sleep(2);
}
}
}
Direct the browser to https://your_domain/eventsource and see a new message every two seconds. Clearly the EventSource messages can be sent from a model.
The only tricky bit was in the JavaScript with setting the URL for EventSource.
PHP Code:
var evtSource = new EventSource(<?= "'".base_url('eventsource/sse', 'https')."'"; ?> );
Notice how I had to explicitly concatenate single quotes around the output of base_url(). Without those JavaScript could not properly evaluate the argument. This is a common issue when combining PHP and JavaScript.
Using the browsers JavaScript console is important when trying to figure out what, if any, failures are occurring. I spotted the above issue right away.
Hopefully, all this helps.
It's not clear to me what you want to happen when processing is complete.
Based on your view it looks like you want to send data back to drive a progress-bar. If so, a message value equal to "100" would make for a good signal to disconnect the EventSource and move on to whatever is supposed to happen.
So I just tried your code out, and when I submit the form, a white page loads with the timestamp being loaded periodically.
data: This is a message at time 2020-02-24T19:49:21-0500
data: This is a message at time 2020-02-24T19:49:25-0500
data: This is a message at time 2020-02-24T19:49:29-0500
And so on.
This is good, but I want these tamestamps to be added to the original page, the one with the form, and for these timestamps to be updates the appeared beneath the submit button. It seems to be returning a new page instead...
Again, thanks for your help, Dave! Do you think you might know what is going wrong?