How to Perform Real-Time Information Exchange
Updated 25 May 2023
4 Min
3721 Views
Sooner or later we all may face the task, which requires to perform the real-time information exchange. I encountered this problem working on the project written in a great framework Yii. The task seemed to be interesting and at first glance rather simple.
User A sends data to the processing by POST method (through existing API /userData). After some time, user B in real time (without page reload) receives a request in the form of a dialog box to confirm user's A data processing. Further, user B simply confirms or cancels the action.
Technologies in use
Having faced with such a non-trivial task, first of all, I began the search for ready-made solutions enabling to exchange information in real time in PHP. As it turned out that the implementation in PHP was not so simple. Taking into account the limited time, websockets implementation in PHP seemed to be a dangerous idea. Likewise, the use of phpdaemon and ratchet libraries was unreliable and time-consuming (perhaps the reason of such bias was the lack of experience with these libraries).
Further searching has led me to Node.js technology in combination with Socket.io library. It was known as a proven and time-tested technology, besides, it was a perfect solution for this particular task.
Still the entire project was developed in PHP and the whole functionality related with user's data sending to the server was already implemented. And the time limits, again, prevented me from remaking the server to Node.js. The solution came by itself:
- Deploy a Node.js server
- Send a request from PHP to Node.js
- Send through socket to the user
Steps to implement the project
There were no problems with the installation of the Node.js server. All information can be found on the official website.
In the root directory of the project, we create a folder nodeServer and a package.json file in it:
{
"name": "nodeJs server",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"socket.io": "^1.3.5",
"body-parser": "~1.12.0",
"express": "~4.9.0"
}
}
Then everything is simple. Write a command npm install in the console to install the libraries.
Create a file app.js, wherein we initialize and run our server.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
//set port
app.set('port', process.env.PORT || 7777);
var server = app.listen(7777, function() {
console.log('info', "Web server successfully started at port " + server.address().port);
});
Start the server in the console
npm start
If you see the message "info Web server successfully started at port 7777", then everything is successful and the server is running.
We proceed to initializing of our socket. Add the code to initialize the socket:
var io = require('socket.io')(server);
io.sockets.on('connection', function (socket) {
console.log('new connection');
socket.on('disconnect', function (data) {
console.log('socket disconnect');
});
});
Let's get down to client's part writing. First of all, we connect socket.io library.
Open the file protected/views/main.php and add
<script src="socket.io.js"></script>
Then we need to connect the server through to the socket
var socket = io.connect('');
Let's check what we've got. Start the server and look what the console outputs at the application launch. If you have done everything correctly, the page is loaded, you should see the message "new connection" and the message "socket disconnect", respectively, when the app is closed.
Next, we modify the project so that we can see what user is connected to us. We announce an array where we are going to keep our connections:
var clients = [];
socket.on('newUser', function(data) {
socket.userId = data.id;
clients[data.id] = socket;
});
Modify the event 'disconnect'
socket.on('disconnect', function (data) {
if ( !socket.userId )
return;
delete clients[socket.userId];
});
And also make the appropriate changes on the client
socket.emit('newUser', {id:73});
where '73' is our current user.
Now let's proceed to the final section: directly to the interaction between PHP and Node.js with Socket.io.
Create on the Node.js server an API to send the confirmation request to the user.
Here is the code to send the request to the user through the socket:
app.post('/confirm', function(req, res) {
var userId = req.body.userId;
if (typeof clients[userId] != 'undefined') {
clients[userId].emit('confirmDialog', req.body);
}
res.status(200);
res.end();
});
Add processing on the client
socket.on('confirmDialog', function(data){
alert('success');
})
Write a function that will send a request to Node.js through curl
{
$url = 'http://localhost:7777/confirm';
$fields = array(
'userId' => $userId
);
$data = json_encode($fields);
//open connection
$ch = curl_init();
//set curl option
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Content-Length: ' . strlen($data)));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
//execute
$resp = curl_exec($ch);
//close connection
curl_close($ch);
}
Then we will just call our method when processing the information of user A (/userData).
If you have done everything correctly when you start a project, you will see the following case. When sending a POST request to the API (/userData) our method sendNodeJsRequest ($userId) will be called, where $userId is a user ID whom we need to transfer information in real time (user B). The method in it's turn will send a request to our Node.js server, and the server will send information in real time to the client through the socket. As a result, the user will see the alert with the word 'success'.
This is just one way to solve this problem. And if you have no opportunity to install the Node.js on the server, you may want to try such libraries as phpdaemon and ratche. However, this method gives excellent results as well as the possibility of the real-time interaction between the server written in PHP and the client.
Discover the best Node.js framework for your project in our article.
Attachment: The code of Node.js server
The final app.js code of Node.js server
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
//get request from php
app.post('/confirm', function(req, res) {
console.log();
var userId = req.body.userId;
if (typeof clients[userId] != 'undefined') {
clients[userId].emit('confirmDialog', req.body);
}
res.status(200);
res.end();
});
//set port
app.set('port', process.env.PORT || 7777);
var server = app.listen(7777, function() {
console.log('info', "Web server successfully started at port " + server.address().port);
});
var io = require('socket.io')(server);
var clients = [];
io.sockets.on('connection', function (socket) {
//When get current user
socket.on('newUser', function(data) {
socket.userId = data.id;
clients[data.id] = socket;
});
socket.on('disconnect', function (data) {
if ( !socket.userId )
return;
delete clients[socket.userId];
});
});
Client's code:
var socket = io.connect('http://localhost:7777');
socket.emit('newUser', {id:73});
socket.on('confirmDialog', function(data){
alert('success');
})
Evgeniy Altynpara is a CTO and member of the Forbes Councils’ community of tech professionals. He is an expert in software development and technological entrepreneurship and has 10+years of experience in digital transformation consulting in Healthcare, FinTech, Supply Chain and Logistics
Give us your impressions about this article
Give us your impressions about this article