I'm using websockets with PHP and some Javascript. I display some information from my database to my client. My goal is to refresh the client when an information has insert into my database. To insert some data in my database, I send a post request from my PC.
At the moment, I can refresh the client to call a function every 10 seconds. But I would like to refresh only if, on that page, a POST request is send.
Here is something that can help you to understand:
- The client's connecting to the web page.
- A SQL select is execute on my database
- The result is received and displayed on the web page.
- The client is connected (via websockets) and see the information from the database.
- Me. If I insert an information on the database, I send a POST request (not from a HTML form, no submit, just a POST request, like if I used Postman to test a webservice). When the request is send, refresh the client by calling a Javascript function...
Here is what I've done:
index.php (Page where the information are displayed)
$(document).ready(function(){
//create a new WebSocket object.
var wsUri = "ws://localhost:9000/server.php";
websocket = new WebSocket(wsUri);
websocket.onopen = function(ev) { // connection is open
$('#message_box').append("<div class=\"system_msg\">Connected!</div>"); //notify user
}
// Call this function every 10 sec to refresh the client
window.setInterval(function(){
displayInfo(1);
}, 10000);
websocket.onmessage = function(ev) {
var msg = JSON.parse(ev.data); //PHP sends Json data
$("#infos").html(msg.message);
};
websocket.onerror = function(ev){$('#message_box').append("<div class=\"system_error\">Error Occurred - "+ev.data+"</div>");};
websocket.onclose = function(ev){$('#message_box').append("<div class=\"system_msg\">Connection Closed</div>");};
});
function displayInfo(r) {
$.post("infos.php",
{ refresh : r},
function(data){
var msg = {
message: data
};
//convert and send data to server
websocket.send(JSON.stringify(msg));
}
);
}
infos.php : Where I execute the SQL select request (works fine)
server.php : Where the code for the server side is. (works fine)
Well. I really don't know how can I achieve this. How to inform and call the function displayInfo(r); if a POST request is send to this page.
Any help is very appriciated. Thank you in advance.
Regards,
Lapinou.
I've seen the server.php
from the link you've provided, and it simply:
- Accepts incoming connections
- Loops through all connected sockets
- If any of these sockets has data, it replies to every other client.
You need to alter this loop and add another source for messages, and you have 2 options. You can pool a DB or open another TCP socket and read from there.
However, the best solution is to use NodeJS with Socket.io and DNode (very elegant solution that works cross-browser and is not that difficult), but you need to be able to install NodeJS on your server. I can provide samples if you want.
EDIT: Here it goes my way of doing it.
I'll assume you are familiar with Debian based distributions (I'm going to install things with APT). First I'll explain some things:
- NodeJS is a server-side javascript interpreter that will run our socket part. In fact, we will use both PHP and NodeJS (the latter only for updating clients, so your existing code will not change much)
- NPM is a command line utility (that comes with NodeJS). Its main purpose is for installing packages (Socket.io and DNode are NPM packages)
- Socket.io is a wrapper around WebSockets that make it works cross-browser. It also contains the server-side handling functions
- DNode is an RPC for communicating with other languages/servers (in this case, with our PHP script)
First we install NodeJS. The version on Ubuntu repo's is veeery old, so we add a PPA from here:
sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get update
sudo apt-get install node
This will install NodeJS and NPM. More info here.
Now cd
into your working directory and create this file: server.js
//import libraries
var io = require('socket.io');
var dnode = require('dnode');
var clients = []; //this array will hold all connected clients
var srv = io.listen(8080, { log: false }); //this port must be different from apache
srv.sockets.on('connection', function(socket){
console.log("Client connected.");
clients.push(socket);
//this will be called when a javascript client sends us something. you can delete this if you don't need it
socket.on('message', function(data){
console.log(data);
});
socket.on('disconnect', function(){
console.log("Lost client.");
var i = clients.indexOf(socket);
clients.splice(i, 1); //remove from array
});
});
var dnode_server = dnode({
//expose a "send" function
send: function(data, cb){
for(i = 0; i < clients.length; i++){
clients[i].emit('update', { //send an "update" message to all connected clients
title: data.title, //some data
text: data.text
});
}
cb(null, false); //inform PHP that the processing is done. You can also return something
}
//you can have multiple functions here
});
dnode_server.listen(5004); //this port should not be accessible from the ouside
Next, install required libraries:
npm install socket.io
npm install dnode
You can run this script using node server.js
Now we need to edit the clientside javascript. Import Socket.io using this:
<script type="text/javascript" src="http://YOURHOSTNAME:SOCKETIOPORT/socket.io/socket.io.js"></script>
Then use it like this:
socket = io.connect('http://YOURHOSTNAME:SOCKETIOPORT');
socket.on('connect', function(data){
alert('Connected!');
});
socket.on('disconnect', function(){
alert('Disconnected :( are you offline?');
});
socket.on('update', function(data){ //our function call
alert(data.title + " " + data.text);
});
You can send data to server like on NodeJS:
socket.emit('message', {foo: 'bar'});
Finally, you want to trigger "update" on all connected clients from a PHP script. For this, we need a PHP library for interfacing DNode. You can find it here and its usage is very simple:
$dnode = new \DnodeSyncClient\Dnode();
$connection = $dnode->connect('localhost', 5004);
$connection->call('send', array(array(
'title' => "My awesome title",
'text' => "My awesome text"
)));
Calling this PHP script will send title and text to your server.js that will broadcast everything to your connected clients.
Hope this helps!