unchanged
Title
Real-time display of server push data using Server-Sent Events (SSE)
Server push technologies
------------------------
There are several methods and techniques that come handy in the case you need to
call an external resource periodically or if you are waiting for a server push,
but I present here an easy and straightforward one using HTML5's [Server-Sent
Events](http://dev.w3.org/html5/eventsource/ "W3C's Editor Draft")
(SSE).
Let's say you have an internal messaging system in your webapp, and you want to
display messages dynamically and real-time to the relevant recipients.
Where's the demo?
-----------------
No demo :-) But here are really easy steps to get it, and get it done.
### Table structure
Let's keep things simple, we'll have a standard User model that is not
represented here, and a Message model based on the following table structure:
~~~
[sql]
CREATE TABLE `Message` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`toUserId` int unsigned NOT NULL,
`message` text NOT NULL,
`new` tinyint NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
KEY `toUserId` (`toUserId`)
);
~~~
### View
Say you want messages to show in any part of the webapp, so you can add an empty
div to your main layout and a simple jQuery snippet firing the SSE call, like
this:
~~~
[php]
<?php
Yii::app()->clientScript->registerScript('message-update', '
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("' .
CController::createUrl('site/getMessage') . '");
source.onmessage = function(event) {
$("#message").prepend(event.data).fadeIn(); // We want to
display new messages above the stack
};
}
else {
$("#message").replaceWith("<div
class=\"flash-notice\">Sorry, your browser doesn\'t support
SSE.<br>Hint: get a real one :-)</div>"); // Don\'t be
desperate, we\'ll see what we can do for you at the end of the wiki
}
', CClientScript::POS_READY);
?>
<div id="message"></div>
~~~
### Controller (SiteController.php)
The app logic will be in our Site controller. The getMessage method will check
at a defined interval (see below) whether there is any new message, and return a
ready-to-display block that will be prepended to our message div.
So here's our controller method. Notice that you need to add the relevant access
rule(s) for that method.
~~~
[php]
<?php
class SiteController extends Controller
{
…
/* Add access rules if needed for getMessage */
…
public function actionGetMessage()
{
$messageList = Message::model()->findAll(array(
'condition' => 'toUserId = :myId AND new = 1',
'order' => 'id DESC',
'params' => array(':myId' =>
Yii::app()->user->_id)
));
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
echo "retry: 10000\n"; // Optional. We tell the browser to
retry after 10 seconds
if(count($messageList)) {
foreach($messageList as $key => $message) {
echo "data: <p>" . $message->message .
"</p>\n";
}
//Now we run a bulk update query in order to flag the just retrieved
messages (new = 0)
$sql = 'UPDATE Message
SET new = 0
WHERE toUserId = ' . Yii::app()->user->_id;
$command = Yii::app()->db->createCommand($sql);
$command->execute();
}
flush();
}
…
}
?>
~~~
As you can notice, it's not real real-time, but a regular check at 10 second
intervals. That is an optional parameter that falls back to the browser default
if not specified.
Of course, the Message table update should be more accurate: with the above
simplistic code, some messages could have been posted to the user during the
method execution, so they would be flagged —wrongly— whatsoever.
Browser support aka does it work in IE?
---------------------------------------
Internet Explorer and Android browser (all versions) [don't support Server-Sent
Events](http://caniuse.com/eventsource) out of the box. Neither do older
versions of Firefox (< 6), Chrome (< 6), Safari (< 5), iOS Safari (<
4), or Opera (< 11).
So should we drop it until IE and Android support it?
-----------------------------------------------------
It's up to you. There's a [polyfill](https://github.com/Yaffle/EventSource) that
gives SSE/EventSource support to IE 8+ and Firefox 3.5+.
More information
----------------
Read more about SSE and Websockets and other techniques:
- [HTML5 and Server-Sent
Events](http://dsheiko.com/weblog/html5-and-server-sent-events)
- [WebSockets vs Server-Sent Events vs
Long-polling](http://dsheiko.com/weblog/websockets-vs-sse-vs-long-polling)
- [Stream Updates with Server-Sent Events - aka Server-Sent Events vs.
Websockets](http://www.html5rocks.com/en/tutorials/eventsource/basics/)
Version française
-----------------
[Tutoriel Yii : Affichage en temps réel de données en provenance du serveur à
l’aide des Server-Side Events (SSE)](http://tellibus.com/blog/1 "Tutoriel
Yii : Affichage en temps réel de données en provenance du serveur à l’aide
des Server-Side Events (SSE)")