I really enjoy making messaging systems and feel they really add that "bit extra" to my site. In this article, I'll be showing you how to make a simple messaging system in PHP.
Note: if you don't want to read everything, you can download a ready-made version of the messaging system at the end of this article.
The first thing we need to do is create the database. You can call it what you like, but for this example, it's known as "messaging". The database will only need to hold messages. For this, we need to create a table called "messages" with the following fields:
nickname - VARCHAR(20) - this holds the users nickname
message - TINYTEXT - holds the users message.
date - TIMESTAMP
ident - CHAR(10) - holds an identification string to make sure the same message is not shown twice
Now, that's really the most difficult part on the MySQL part. We'll now be using PHP, MySQL and JavaScript for the bulk of this article.
First of all, create a file called config.php. You'll want to put the following information into it:
<?php
//Connection to MySQL Server:
$access = @mysql_connect('localhost','root','password') or die ('ERROR. Could not connect.');
// Select database:
@mysql_select_db('messaging', $access) or die ('ERROR. Could not connect.');
?>
This code creates a connection to the MySQL server and selects a database (messaging). You'll need to replace 'localhost', 'root' and 'password' with the details which correspond to your MySQL server. 'messaging' will have to be changed if your database is called something else.
When the script can not connect, it will die with an error message saying "ERROR. Could not connect."
You can now save and close config.php.
Next, create a file called index.php. This will display the messaging system. You need to put the following PHP at the top of your file:
<?php
include('config.php');
$guest_code = rand(1000, 9999);
?>
This first includes the config file, and then creates a random code, called a "guest code". This is so guests can automatically be assigned a username - guest1040, guest3943, etc.
You'll now need to put the basic "starting HTML" in. Here's an example:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Messaging System</title>
</head>
<body>
</body>
</html>
Just before </head>, you should put this code:
<style type="text/css">
body, html {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
margin: 0;
}
form {
margin: 0;
}
</style>
It will make everything look better later.
Within <body> and </body>, put the following code:
<div id="talk" style="height: 380px; width: 580px; border: 1px solid #000000;">
</div>
This basically makes a box, which is 380px high, 580px wide and has a 1 pixel, black solid border. All the other HTML will be contained within this div.
Next, between <div id="talk" style="hei…. and </div> put:
<form method="post" action="javascript:sendMessage()">
</form>
When the user wants to send a message, this code tells the browser to call the JavaScript function sendMessage(), which will complete the request. The message will be sent via AJAX.
Now, between <form method="post" action="jav… and </form> put the following code:
<div style="width: 580px; height: 380px; background: #DDDDDD; border: none;">
<div style="height: 25px;padding-top: 6px; padding-left: 6px; padding-bottom: 6px;">
</div>
</div>
That code makes a box with a light grey/silver (#DDDDDD) background. The inner div is where we'll put the nickname input box.
To create the nickname input box, put the following code between <div style="height: 25px; padding-top: 6… and </div>:
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td width="60">Nickname:</td>
<td>
<input type="text" name="nickname" maxlength="20" id="nickname" onkeyup="this.value = this.value.replace(/[^A-Z0-9 ]/gi, ")" onchange="this.value = this.value.replace(/[^A-Z0-9 ]/gi, ")" style="height: 16px; width: 500px;" onblur="if(!this.value) {this.value = 'Guest<?php echo $guest_code; ?>'; }" />
</td>
</tr>
</table>
This creates a table with two columns, one which says Nickname: and one which contains an input box. The important part in this code is the input box. Whatever the user enters here becomes his/her nickname. If the user doesn't enter anything, it is set to Guest####.
After the code you just inserted, it should say </div>. Just after this, put:
<div style="padding-left: 6px; width: 566px;">
<div style="background: #FFFFFF; height: 277px; border: 1px solid #000000; padding: 5px; overflow: auto; background: url(images/tr_light_DDDDDD.png) no-repeat #FFFFFF top right; width: 554px;" id="messages">
</div>
</div>
This code creates the area where the messages will be displayed. You'll notice that it includes a background image - images/tr_light_DDDDDD.png - you can download this file from the end of this article.
Now, directly after that, put:
<div style="padding-left: 6px; width: 566px; padding-top: 10px;">
<div style="background: #FFFFFF; height: 36px; border: 1px solid #000000;">
<table cellspacing="0" cellpadding="0" border="0">
<tr>
<td width="506">
<input type="text" id="input" style="width: 500px; height: 33px; border: 0px solid #FFFFFF; overflow: auto;" maxlength="200" tabindex="0" />
</td>
<td width="58">
<input type="submit" value="Send" style="height: 36px; width:58px;" /> </td>
</tr>
</table>
</div>
</div>
This puts a text input box and a Send button. This allows the users to write messages.
Now that's pretty much the HTML finished, we now need to work on the JavaScript.
Just before </body> in your document, put the following:
<script type="text/javascript" language="javascript">
</script>
This lets the browser know that everyting between <script type…> and </script> is JavaScript code. If you like, you can put the JavaScript into an external file, say scripts.js, and include it.
We are now working between <script …> and </script>. Put your code here, until I say otherwise.
The first line of JavaScript you'll need is:
var oldNickname = '<?php if(isset($_COOKIE['nickname'])) { echo preg_replace('/[^A-Z0-9 ]/i', ", $_COOKIE['nickname']); }else{ echo 'Guest'.$guest_code; } ?>';
This variable, oldNickname, holds the previous nickname. We need this variable so the users can be notified when a user changes their nickname. When the page loads, it will contain their current nickname, if they have one set (using cookies), or it will be set to the Guest value.
Next, inset this code:
function shttp(){
var sh = false;try {sh = new XMLHttpRequest();} catch(e) {try {
sh = new ActiveXObject("Msxml2.XMLHTTP");}catch(e){try{sh = new ActiveXObject("Microsoft.XMLHTTP");}catch(e){sh=false;}}}return sh;
}
var comm = shttp();
var check = shttp();
This is the AJAX section, which allows us to update the page without having to refresh the page. comm is used to send messages, while check is used to check for messages.
Directly beneath that, put:
var idents = new Array();
var idents50 = new Array();
This holds the idents, which identifies the messages the client has recieved. This lets us make sure that no messages are displayed twice. idents50 holds the 50 messages currently being displayed, while idents holds the last 500.
Next, put:
var lastupdated = '<?php echo date('ymdHis'); ?>'; // Last Update Time (YYMMDDHHMMSS)
This holds the last update time. This last update time is sent with the update request, so only new messages are downloaded.
Now, insert the following:
var connecting = false;
var count = 0;
connecting is either true or false. It's starting value must be false. It enables us to see whether we are currently connecting, so we don't use the connection twice. count holds the number of times that we have tried connecting. It allows the script to timeout and use the connection, even if connecting is true.
We now need a function called start() which in turn starts the updating process. Put this after the previous JavaScript code:
function start() {
var ti=document.getElementById('talk');
document.getElementById('input').focus();
document.getElementById('nickname').value = '<?php if(isset($_COOKIE['nickname'])) { echopreg_replace('/[^A-Z0-9 ]/i', ", $_COOKIE['nickname']); }else{ echo 'Guest'.$guest_code; } ?>';
dataComm();
}
When this code is called, it does a few things. The first thing it does is put focus onto the message input box (moves the text cursor there). The second thing it does is set the nickname. The third, and final, thing it does it call dataComm() which starts the updating process.
Before we make the dataComm() function, we need to make a function which deals with the request. After the previous function, put this one:
function check_process() {
try {
if(check.readyState == 4){
rt = check.responseText;
data = rt.split(/<>/g);
for(var a = 0; data[a]; a++) {
if(data[a].substr(0, 1) == '!') {
lastupdated = check.responseText.substr(check.responseText.length-12);
}else{
if(!idents[data[a].substr(0, 12)]) {
idents = idents.slice(0, 500);
idents50.splice(0, 0, data[a].substr(0, 12));
idents50 = idents50.slice(0, 50);
var n = document.getElementById(idents50[50]);
if(n) n.parentNode.removeChild(n);
idents[data[a].substr(0, 12)] = 1;
newcont = document.createElement("div");
newcont.setAttribute("id",data[a].substr(0, 12));
newcont.style.paddingBottom = '7px';
newcont.innerHTML = data[a].substr(12);
document.getElementById("messages").appendChild(newcont);
document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight - document.getElementById('messages').clientHeight;
}
}
}
count = 0;
connecting = false;
}
}catch(e) {}
}
This code is surrounded in a try-catch block, so, if there are any errors, they will not be displayed to the user. One of the first things this function does is get the response and split it at every <>. <> is used to seperate messages. Messages which naturally contain <> will not be affected because they are encoded.
The next thing it does is cycle through each message. If the message begins with !, then it is the current server time, which is stored in the lastupdated variable. If not, the message will first contain the ident, followed by the message. If the message hasn't already been displayed, it is shown to the user. Old messages are also removed (saves memory).
Now, the dataComm() function:
function dataComm() {
if(connecting == false) {
connecting = true;
check.open("GET", "check_messages.php?d="+lastupdated, true);
check.onreadystatechange = check_process;
check.send(null);
}
count++;
if(count > 3) {
count = 0; connecting = false;
}
setTimeout("dataComm()", 3000);
}
This function basically makes an AJAX request to check_messgaes.php, which returns the latest messages from the MySQL database. It also calls itself again in 3 seconds.
Now we can recieve messages, we need to make a way to send them. Again, this is done with an AJAX request. The function called to send a message is sendMessage(), but before we create this, we'll create the send_response() function which will process the response:
function send_response() {
if(comm.readyState == 4){
if(comm.responseText == '999') {
alert('Your message could not be sent because of an undefined error');
}else if(comm.responseText == '922') {
alert('Your message could not be sent because it exceeded the maximum length of 255 characters');
}
document.getElementById('input').disabled = '';
document.getElementById('input').value = '';
document.getElementById('input').focus();
}
}
When the message could not be sent, an error message is sent instead. If 992 is recieved, the message was longer than 255 characters, which is not allowed (because it can not be stored in the database). 999 is sent if the error is a different one. If you choose to further develop the system, you may want to add more error codes - e.g. "991 - Server Side Error," etc.
Now we have a function to handle the response, we need a function which make the request. This is done via the sendMessage() function:
function sendMessage() {
if(document.getElementById('input').disabled) {
return;
}
document.getElementById('input').disabled = 'disabled';
comm.open("POST", "send_message.php", true);
comm.onreadystatechange = send_response;
comm.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
comm.send('oldNick=' + encodeURIComponent(oldNickname) + '&m=' + encodeURIComponent(document.getElementById('input').value) + '&n=' + encodeURIComponent(document.getElementById('nickname').value.substr(0, 20)));
if(oldNickname !=document.getElementById('nickname').value.substr(0, 20)) {
oldNickname = document.getElementById('nickname').value.substr(0, 20);
}
}
The first thing the sendMessage() functions does is check whether it is allowed to send a message. It does this by checking if the message input box is disabled or not. If it isn't disabled, it is set to disabled before continuing. Next, and most importantly, a request is made to the send_message.php page which will inset the message into the database.
That is the end of defining JavaScript functions. We just need to start everything using the start() function we created:
start();
Now, we've pretty much done all of the MySQL, HTML and JavaScript needed for this to run. But, that's not the end of the system. We are still to create send_message.php and check_messages.php for the system to function correctly.
We'll start of by creating the check_messages.php file. Open a new, blank file.
The first thing we need to do in our file is include the config.php file; this allows the script to access the MySQL server:
include('config.php');
On the next line, we need to make sure the required parameters were given:
if(!isset($_GET['d'])) { die('999'); }
If the date (d) parameter was not provided, the undefined error code 999 will be outputted.
On the line underneath, you need to put this code:
$_GET['d'] = substr(preg_replace('/[^0-9]/', ", $_GET['d']), 0, 12);
This line of code ensures that the d parameter is 12 characters long and only contains numbers.
Next, we need to get the latest messages from the database:
$result = @mysql_query('SELECT nickname, message, ident FROM `messages` WHERE date >= \''.mysql_real_escape_string($_GET['d']).'\' AND date >= DATE_ADD(\".date('ymdHis').'\', INTERVAL -15 SECOND) LIMIT 0, 30');
while($row = @mysql_fetch_array($result)) {
echo '<',$row[2],'>',htmlspecialchars($row[0]),' says:<br /> ',htmlspecialchars($row[1]),'<>';
}
The query gets all messages which were posted after the d parameter, and within the last 15 seconds. The number of rows that can be returned is limited to 30.
Directly following that, you want to give the client the server time:
echo '!'.date('ymdHis');
If you want, you can place this code in the script to delete old messages:
if(rand(0, 100) > 99) { // 1% chance of clearing up
@mysql_query('DELETE FROM `messages` WHERE date < DATE_ADD(\''.date('ymdHis').'\', INTERVAL -20 SECOND)');
}
And that's it for the check_messages.php file. Now onto send_message.php.
As in check_messages.php, send_message.php required MySQL access. To do this include the config file:
include('config.php');
Again, we need to make sure that the required parameters were given:
if(!$_POST['m']) { die(); }
if(!$_POST['n']) { $_POST['n'] = 'Guest'; }
The required parameters for this script are the message, m, and nickname, n.
Because we can't store any message greater than 255 characters in length, we need to check it is the right size:
if(strlen($_POST['m']) > 200) {
die('922');
}
Before we add the message to the database, we want to see if the user has changed their nickname. If they have, a message will be posted notifying everybody:
if($_POST['oldNick'] && ($_POST['n'] != $_POST['oldNick'])) {
$result = @mysql_query('INSERT INTO `messages` (nickname, message, date, ident) VALUES (\".mysql_real_escape_string('Server Notice').'\', \".mysql_real_escape_string($_POST['oldNick'].' has changed his/her nickname to '.$_POST['n']).'\', \".date('ymdHis').'\', \".substr(md5(time().rand(1000, 9999)), 0, 10).'\')');
}
Now it's time to insert the message into the table:
$result = @mysql_query('INSERT INTO `messages` (nickname, message, date, ident) VALUES (\''.mysql_real_escape_string($_POST['n']).'\', \".mysql_real_escape_string(substr($_POST['m'], 0, 1000)).'\', \".date('ymdHis').'\', \".substr(md5(time().rand(1000, 9999)), 0, 10).'\')');
Congratulations! You should now have a fully functioning messaging system. If you don't, do not hesitate to leave a comment to seek assistance.
If you do decide to use the messaging system on your site, it would be appreciated, but not required, if you placed a link to bitfilm.net on your site somewhere.
You can download a ready-made version: Messaging System


really good… code are very interesting….. =D
doesn't seems to work in IE and opera!!!!!…
Thanks for your message "kk",
The last I checked, it did work in Internet Explorer and Opera, amongst many other browsers. There may have been something I changed between writing the scripts and writing the article, so I'll definitely look into it.
-Brendon
Hello, I am quite impressed with the coding you provide now I have to also do the same for my website and have to add one more feather in its cap.
One more thing can you please provide us a code to make a call to a person as well using the same resources.
Thank You
Rony