I desired to construct a real-time notification system using sockets without using any third-party services, such as Pusher, etc. I simply desired the ability to send alerts from PHP to the client and display them quickly on the web application, similar to Facebook notifications. First I came across the ratchet library, which worked well, but a problem arose when I attempted to set it up on a secure connection (https) on my host (siteground). I tried apache proxy module and everything else suggested on the internet, but to no avail (it appears siteground has a problem with ratchet on https), so I ultimately had to abandon ratchet. Then I considered utilizing socket.io with Node+PHP, and in my study I came across the elephant.io library (albeit it hasn't been updated in a while), which worked marvelously well on both non-secure and secure protocols, enabling us to send and receive messages from PHP with a node-based server. Here are the procedures I took to get my notification system to function properly.
Install elephant.io via composer for your PHP application:
composer require wisembly/elephant.io
Create a directory at the root of your project and create a package.json file with the following contents:
{
"name": "elephantIO_example",
"version": "3.0.0",
"main": "server.js",
"scripts": {
"start": "supervisor --debug server.js"
},
"dependencies": {
"socket.io": "~1",
"winston": "*"
}
}
Execute npm install —save on the newly created directory. This will install the logger and socket.io libraries.
Create a file server js containing the following code in the same freshly created directory:
var server = require('http').createServer(),
io = require('socket.io')(server),
logger = require('winston'),
port = 3001;
// Logger config
logger.remove(logger.transports.Console);
logger.add(logger.transports.Console, { colorize: true, timestamp: true });
logger.info('SocketIO > listening on port ' + port);
io.on('connection', function (socket){
var nb = 0;
logger.info('SocketIO > Connected socket ' + socket.id);
socket.on('broadcast', function (message) {
++nb;
logger.info('Elephant.IO broadcast > ' + JSON.stringify(message));
// send to all connected clients
io.sockets.emit("broadcast", message);
});
socket.on('disconnect', function () {
logger.info('SocketIO : Received ' + nb + ' messages');
logger.info('SocketIO > Disconnected socket ' + socket.id);
});
});
server.listen(port);
If you execute server.js through node by typing node server.js, you should receive a message indicating that the server has started on the chosen port.
Insert the following javascript code into your application's page/footer:
<script src="https://cdn.socket.io/4.5.0/socket.io.min.js"
integrity="sha384-7EyYLQZgWBi67fBtVxw60/OWl1kjsfrPFcaU0pp0nAh+i8FD068QogUvg85Ewy1k" crossorigin="anonymous"></script>
<script>
var socket = io.connect('//127.0.0.1:3001');
socket.on('connect', function () {
console.log('connected');
socket.on('broadcast', function (data) {
//console.log(data);
//socket.emit("broadcast", data);
alert(data.text);
});
socket.on('disconnect', function () {
console.log('disconnected');
});
});
</script>
Here's how to communicate with all linked clients:
require __DIR__. '/vendor/autoload.php';
use ElephantIOClient;
use ElephantIOEngineSocketIOVersion1X;
$client = new Client(new Version1X('//127.0.0.1:3001'));
$client->initialize();
// send message to connected clients
$client->emit('broadcast', ['type' => 'notification', 'text' => 'Hello There!']);
$client->close();
And that concludes the discussion.
I was running CentOSv6 and installed node using this procedure. Then I built a simple php file that will be executed by cron so that the node server is automatically started or restarted if it is not running:
$nodePath = 'your node binary path here';
$filePath = 'your server.js file path';
shell_exec($nodePath . ' ' . $filePath);
and then set that file in cron to run at your desired intervals.