That solution will definitely work, using setTimeout
to check for new messages every second or so. There are other technologies such as comet although these are not possible in PHP, as stated in the question.
Here is an example that uses PHP and stores chat history in an SQL database, the ajax function to get new chat messages:
//Updates the chat
function updateChat(){
$.ajax({
type: "GET",
url: "update.php",
data: {
'state': state,
'file' : file
},
dataType: "json",
cache: false,
success: function(data) {
if (data.text != null) {
for (var i = 0; i < data.text.length; i++) {
$('#chat-area').append($("<p>"+ data.text[i] +"</p>"));
}
document.getElementById('chat-area').scrollTop = document.getElementById('chat-area').scrollHeight;
}
instanse = false;
state = data.state;
setTimeout('updateChat()', 1);
},
});
}
As you can see the last line uses setTimeout
to call the function every 1 second.
Messages are sent separately by a different function:
//send the message
function sendChat(message, nickname) {
$.ajax({
type: "POST",
url: "process.php",
data: {
'function': 'send',
'message': message,
'nickname': nickname,
'file': file
},
dataType: "json",
success: function(data){
},
});
}
As I mentioned in my comment above, there are some advantages to using server technologies other than PHP. Most PHP solutions use a database to persist chat messages between requests to the server, this creates a lot more server overhead than is really needed, a node.js solution can instead store the messages in an array that stays in memory within the server, and in addition use sockets see here for an example.
Edit - to cache an sql query in memory
If you are using MySQL it is possible to prepend your query with a comment to imply that the query should be cached in memory, something like:
$res = $mysqli->query("/*" . MYSQLND_QC_ENABLE_SWITCH . "*/" . "SELECT message FROM chatroom WHERE id = $roomId");
For more information see example 1, here. The example times the queries and could be useful as a benchmark on your Server.
Caching can occur on the server even if the code does not explicitly ask for it, after all the amount of memory required to store the contents of a chatroom is very small - it's only a few lines of text! The example I took the Javascript code from, above, stores the text in a file, which would almost certainly be stored in memory on the Web Server. If the db server is running on the same host as the web site then the request may well not result in any disk activity, making the overhead also very small. The webserver / db connection may also be in memory rather than sockets.
The best solution will very much depend on your server setup, best to get something working, then optimise it. I do know from experience that the node.js
solution is very fast.
Edit - Answer to flag question
Setting a flag in the client Javascript would not work, as other clients could submit messages without the flag for the current client being reset. Setting a flag in the PHP on the server is tricky, persistent variables that are not specific to clients (from sessions or cookies), and not stored in databases have to be saved in files: PHP: persistent variable value. The static
keyword is not quite the same as it would be in C or similar language. This is one of the main advantage of using Node.js
, persistent arrays are very easy to create.
One solution would be to save the messages as json
in a file, append each new message as it is received, and return the whole file to the user, once a second. The file could be restricted to 100 lines or so, this would ensure that it stays stored in cache memory somewhere (ramdisk, OS disk cache, or at worse hardware cache on the harddisk itself).