How to build chat application in PHP?

Chatting is most popular and used application today.I am going to describe Group Chat here.

To learn chat application you should know the following.

  • jQuery
  • Ajax
  • PHP

Concept behind Chat Application

  • For getting instant messages we need to trigger an Ajax call after certain interval which we will check for new messages in the database by comparing the current message on the page and append those messages to messages section.
  • User registration section if required.
  • Admin section for managing the User ban,creating groups etc.

Following are source code here.
Database structure for chat application.

CREATE TABLE IF NOT EXISTS `chat` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `chat_group_id` int(11) NOT NULL,
  `author_id` int(11) NOT NULL,
  `author_role` varchar(255) NOT NULL,
  `message` longtext NOT NULL,
  `create_date` datetime NOT NULL,
  `status` tinyint(4) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=13 ;

CREATE TABLE IF NOT EXISTS `chat_group` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(512) NOT NULL,
  `created_time` datetime NOT NULL,
  `status` tinyint(4) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=14 ;

CREATE TABLE IF NOT EXISTS `guest` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `user_name` varchar(255) NOT NULL,
  `avatar` varchar(255) NOT NULL,
  `last_logged_in` datetime NOT NULL,
  `create_date` datetime NOT NULL,
  `ip` varchar(255) NOT NULL,
  `browser` varchar(255) NOT NULL,
  `online_status` tinyint(4) NOT NULL,
  `user_role` int(11) NOT NULL,
  `ban_by` int(11) NOT NULL,
  `cookie` varchar(255) NOT NULL,
  `status` tinyint(4) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=21 ;

CREATE TABLE IF NOT EXISTS `online_users` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `user_role_id` int(11) NOT NULL,
  `last_logged_in` datetime NOT NULL,
  `browser` varchar(512) NOT NULL,
  `ip` varchar(255) NOT NULL,
  `status` int(11) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=730 ;

index.php

<?php  include_once 'includes/header.php';?>
<?php 
session_start();
include_once 'config.php';
include_once "php/classes/chat-main.class.php";
$group_id	=	0;
if(isset($_REQUEST['group_id'])) 
$group_id		=	$_REQUEST['group_id'];
$allMessage		=	ChatMain::getAllChatMessages($group_id);
$allsmiley		=	ChatMain::fetchAllSmiley();
//print_r($_SESSION);
$username		=	"";
if(!isset($_SESSION['user']['id']) && isset($_SESSION['username'])){
	$username   = $_SESSION['username'];
}else{

$username		=	ChatMain::getUserName($_SESSION['user']['id'],$_SESSION['user']['role']);
}

?>
  <div id="chat_wrap">
     <div id="top_buttons">   
	  <input type="text" placeholder="Username" id="user_name" class="user_name" value="<?php echo $username;?>">
	  <input type="button" value="Chat">   
    </div>
    <div id="chat_header">
      <div class="menu"></div>      
      <div class="title">Some Text Here</div>
    </div>
    <div id="message_wrap">    
<?php if(!empty($allMessage)){foreach($allMessage as $message){?>	
        <div class="message" id="msg_<?php echo $message->ID;?>">
          <table class="msg_table" border="0" width="100%">
            <tbody>
              <tr>
                <td scope="col" class="time"><?php echo date("h:i a",strtotime($message->create_date));?><br/><?php echo date("m/d/Y",strtotime($message->create_date));?></td>
                <td scope="col" class="user">
				<?php if(ChatMain::getAvatar($message->author_id,$message->author_role)!=""){?>
					<img src="<?php echo ChatMain::getAvatar($message->author_id,$message->author_role);?>" width="40px">
				<?php }else{?>
				<img src="img/default.jpg" width="40px">
		<?php }?></td>
                <td scope="col" class="user_name">
				<?php 
				if(ChatMain::getUserTextColor($message->author_id,$message->author_role)!='Text Color'){
				?>
				<font color="<?php echo ChatMain::getUserTextColor($message->author_id,$message->author_role);?>">
				<?php echo ChatMain::getUserName($message->author_id,$message->author_role);?>
				</font>
				<?php }else{?>
				<?php echo ChatMain::getUserName($message->author_id,$message->author_role);?>
				<?php }?>
				</td>            
                <td scope="col" class="message_text">
				<?php echo ChatMain::parseString($message->message);?>
				<?php if(isset($_SESSION['user']['role']) && $_SESSION['user']['role']=='admin'){?>
				<a href="javascript:void(0);" style="float:right;text-decoration: none;" class="deleteChat" rel="<?php echo base64_encode($message->ID);?>">[X]</a> &nbsp;|
				<a href="javascript:void(0);" style="float:right;text-decoration: none;" class="banUser" rel="<?php echo base64_encode($message->author_id."_".$message->author_role);?>">[O]</a>
			<?php }?>
				</td>
              </tr>
            </tbody>
          </table>
        </div> <!-- end message -->
<?php }}?>
    </div> <!-- end message_wrap --> 
    <div id="message_text_area">
      <textarea rows="4" placeholder="Send a text message" name="chat_msg" class="chat_msg"></textarea>
      <img class="popup_btn" src="image/smile.png">
      <div class="smiley_popup">
	  <?php foreach($allsmiley	 as $key=>$val){?>
        <div>
          <a href="javascript:void(0);" rel="<?php echo $key;?>" class="smiley"><img src="smiley/<?php echo $val;?>"></a> 
        </div>
		<?php }?>
      </div>
    </div> <!-- end text area -->
	
    <div class="buttons">
      <input name="Chat" value="" class="setting1" type="button">
      <div class="popup setting">
        <div><p></p></div>
		<input type="text" value="Text Color" class="text_color">
		<input type="button" value="Text Color" class="text_color">
        <input type="button" value="Timestamps">
        <input type="button" value="Hide Chat">
        <input type="button" value="Chat Popout">
      </div>
      <input name="Chat" value="" class="setting2" type="button">
      <div class="popup viewer_list">
        <p>
          Viewer List
        </p>          
          <ul>
            <li><img src="image/user.gif">Name</li>
            <li><img src="image/user.gif">Name</li>
            <li><img src="image/user.gif">Name</li>
          </ul>
      </div>
      <input name="Chat" value="Chat" id="btn_submit" class="btn_submit btnSubmit" type="button">
	  <input type="hidden" id="num" value="<?php echo count($allMessage);?>">
      <input type="hidden" id="group" value="<?php echo $group_id;?>"> 
    </div>
  </div><!-- end chat wrap -->
  <?php  include_once 'includes/footer.php';?>

The following javascript code required to save and get the recent messages for the users.
custom.js

jQuery(document).ready(function(){
var $pickerInput;
 $('.text_color').ColorPicker({ 
      onSubmit: function(hsb, hex, rgb, el) {
          $(el).val('#' + hex);
          $(el).ColorPickerHide();
      },
      onBeforeShow: function () {
          $(this).ColorPickerSetColor(this.value);
          $pickerInput = $(this);
      },
      onHide: function(picker) {
	   // alert('#' + $(picker).find('.colorpicker_hex input').val());
          $pickerInput.val('#' + $(picker).find('.colorpicker_hex input').val());
      }
  })
  .bind('keyup', function(){
      $(this).ColorPickerSetColor(this.value);
  });

jQuery('.smiley').click(function(){
var smiley 		 =	jQuery(this).attr('rel');
var msg			=	jQuery('.chat_msg').val();
var appendmsg	=	msg+" "+smiley.trim();
jQuery('.chat_msg').val(appendmsg);
$(".smiley_popup").fadeOut(); 
});
 $(".popup_btn").click(function() { 
	$(".smiley_popup").fadeIn(); 
 });
$('.text_color').click(function(){

	jQuery('.setting').hide();
});
setTimeout(function() {
    getAllChatMessage();
}, 2000);
jQuery("#btn_submit").click(function(){
	submitMessage();
});
jQuery(".chat_msg").keypress(function(e) {
    if(e.keyCode == 13) {
		submitMessage();
    }
});

function submitMessage(){
	if(jQuery('#user_name').val()!=""){
	if(jQuery(".chat_msg").val()!=""){
	var color_code=	jQuery('.text_color').val();
	var group = jQuery('#group').val();
	jQuery.ajax({
		url :"ajax.php?action=saveChat",
		data:{color_code:color_code,group:group,chat_msg:jQuery(".chat_msg").val(),user_name:jQuery('#user_name').val(),url:jQuery('.url').val()},
		type: 'post',
		success:function(res){
			if(res==-1){
				jQuery(".update").html("<font color='red'>You need to login first!!</font>");	
				jQuery('.loginDiv').show();
			}else if(res==-2){
				alert("You have baned for chat. Please contact admin.");	
			}
			else
			jQuery(".chat_msg").val("")
		}
	});
	}else{
			jQuery(".update").html("<font color='red'>Please enter message.</font>");	
	}
	}else{
			alert("Please enter username");
			jQuery(".update").html("<font color='red'>Please enter user name .</font>");	
	}
}

function getAllChatMessage(){
var numOfOldMessage	=	jQuery('#num').val();
var group = jQuery('#group').val();
jQuery.ajax({
	url :"ajax.php?action=getAllChat",
	data:{num:numOfOldMessage,group:group},
	type: 'post',
	success:function(res){
	   //console.log("Res=="+res);
		if(res!=""){
			var data	=	res.split("<split>");		
			var text = data[0];
			jQuery("#message_wrap").prepend(text);
			jQuery('#num').val(data[1])
			$('.message_wrap').scrollTop(0);
		}
		setTimeout(function() {
			getAllChatMessage();
			}, 2000);
		}
})

}

jQuery(".btnLogin").click(function(){
jQuery.ajax({
	url :"ajax.php?action=login",
	data:jQuery("#frmLogin").serialize(),
	type: 'post',
	success:function(res){
		if(res==-1)
		jQuery(".update").html("<font color='red'>You need to login first!!</font>");	
		else{
			window.location.reload();
		}
	}
});
});
jQuery(".deleteChat").click(function(){
var x = confirm("Do you want to delete");
var id =	jQuery(this).attr('rel');
var num =	 parseInt(jQuery('#num').val());
if(x){
	jQuery.ajax({
		url :"ajax.php?action=deleteChat",
		data:{id:id},
		type: 'post',
		success:function(res){
		res	=	res.trim();
			if(res){
				jQuery("#msg_"+res).remove();	
				num	=	num-1;
				jQuery('#num').val(num);
			}
			
		}
	});
}
});
jQuery(".banUser").click(function(){
var x = confirm("Do you want to ban user");
var id =	jQuery(this).attr('rel');
if(x){
	jQuery.ajax({
		url :"ajax.php?action=banUser",
		data:{id:id},
		type: 'post',
		success:function(res){
		res	=	res.trim();
			if(res==1){
				
			}
			
		}
	});
}
});
});

function SignOut(){
jQuery.ajax({
		url :"ajax.php?action=SignOut",
		type: 'post',
		success:function(res){
		res	=	res.trim();
			if(res==1){
				window.location.reload(true);
			}
			
		}
	});
}


ChatMain.php, which manage the all operations for saving and getting chat messages.

<?php

class ChatMain{

	 public static $arr	= array();
	public function __construct(){
	  $link	=	mysql_connect('localhost','your_user_name','your_password');
	  $db   = mysql_select_db('database_name',$link);
	 $array			=	self::fetchAllSmiley();
	}
	public static function submitChat($message,$group_id=0){
		if(!isset($_SESSION['user']['id']))
		return -1;
		$author_id		=	$_SESSION['user']['id'];
		$author_role	=	$_SESSION['user']['role'];
		if(self::isBanUser($_SESSION['user']['user_name'],$author_role,$_SERVER["REMOTE_ADDR"])){
		
		$message		=	mysql_real_escape_string(strip_tags($message,'<img>'));
		$date			=	date("Y-m-d H:i:s",time());
		$status			=	1;
		$query			=	"INSERT INTO chat (ID,chat_group_id, author_id,author_role,message, create_date, status)
					VALUES (NULL, '$group_id','$author_id','$author_role', '$message', '$date', '$status');";
		if(mysql_query($query))
			echo "1";
			
	   }else{
			
			// for ban user
			
			echo "-2";
	   }			
	}
	public static function login($user_name='',$user_pass=''){
		$query = "SELECT * FROM users WHERE user_name='".mysql_real_escape_string($user_name)."' AND user_pass='".md5($user_pass)."'";
		$result = mysql_query($query);
		$row	=	mysql_fetch_object($result);
		$_SESSION['user']['id']			=	$row->ID;
		$_SESSION['user']['user_name']		=	$row->user_name;
		$_SESSION['user']['role']								=	$row->role;
		if($row->user_role==1){
			$_SESSION['user']['role']			=	"admin";
		}
		else if($row->user_role==0){
			$_SESSION['user']['role']			=	"user";
		}
    }
	public static function getAllChatMessages($group_id=0){
		$query = "SELECT * FROM chat WHERE status=1 AND chat_group_id=$group_id ORDER BY ID DESC";
		$result     = mysql_query($query);
		if($result){
			while($row = mysql_fetch_object($result)){
				$results[] = $row;
			}
			return ($results);
		}
    }
	public static function getChatMessages($limit,$group_id=0){
		$query 		=  "SELECT * FROM chat WHERE status=1 AND chat_group_id=$group_id ORDER BY ID DESC LIMIT $limit";
		$result     =  mysql_query($query);
		$array		=  array();
		if($result){
		while($row = mysql_fetch_object($result)){
			$array['ID']			= $row->ID;
			$array['create_date']	= $row->create_date;
			$array['message']		= $row->message;
			$array['author_id']		= $row->author_id;
			$array['author_role']	= $row->author_role;
			$array['message']		= self::parseString($row->message);
			$array['avatar']		= ChatMain::getAvatar($row->author_id,$row->author_role);
			//print_r($array);
			$results[]  			= $array;
		}
		
		return ($results);
		}
    }
	public static function getAvatar($user_id,$role=''){
		if($role=="guest")
		$table_name	=	"guest";
		else
		$table_name = "users";
		
		$query 		= "SELECT avatar FROM $table_name WHERE ID=$user_id";
		$result     = mysql_query($query);
		if($result)
		$row		=	mysql_fetch_object($result);
		return $row->avatar;
    }
	public static function checkUserExists($user_name,$avatar=''){
		$query = "SELECT * FROM users WHERE user_name='".mysql_real_escape_string($user_name)."'";
		$result = mysql_query($query);
		if(!$result)
		 $result ="";
		 else
		 $row	=	mysql_fetch_object($result);
		if(empty($row->ID)){
			$query2  = 	"SELECT * FROM guest WHERE user_name='".mysql_real_escape_string($user_name)."' AND ip='".$_SERVER["REMOTE_ADDR"]."'";	
			$resultguest  = 	mysql_query($query2);
			
			if(mysql_num_rows($resultguest)>0){
			    $record									=	mysql_fetch_object($resultguest);
				$_SESSION['user']['id']			=	$record->ID;
				$_SESSION['user']['user_name']		=	$record->user_name;
				$_SESSION['user']['role']			=	"guest";	
				return $record->ID;
				}
			else{
				$query		=	"INSERT INTO `guest` (ID, user_name, avatar, create_date, last_logged_in ,browser,ip,status)
								VALUES (NULL, '$user_name', '$avatar', '".date('Y-m-d h:i:s',time())."','".date('Y-m-d h:i:s',time())."','".$_SERVER['HTTP_USER_AGENT']."','".$_SERVER['REMOTE_ADDR']."','1');";
				if(mysql_query($query)){
					$query 		 = "SELECT * FROM users order by ID desc LIMIT 1";

					$resultData	 = 	mysql_query($query);
					$id			 = mysql_insert_id();
					$_SESSION['user']['id']			=	$id;
					$_SESSION['user']['user_name']		=	$user_name;
					$_SESSION['user']['role']		=	"guest";
					
					return $id;
				}
			}
		}else{
			return "-1";
		}	
	}
	public static function updateAvatar($avatar=''){
		if($_SESSION['user']['id']=="" && $avatar=="")
		return;
		$user_id	=	$_SESSION['user']['id'];
		$role		=	$_SESSION['user']['role'];
		
		if($role=="guest")
		$table_name	=	"guest";
		else
		$table_name   = "users";
		$query1  	  = "SELECT * FROM $table_name WHERE ID=".mysql_real_escape_string($user_id);	
		$result1  	  = mysql_query($query1);
		if($result1)
		$row		  =	mysql_fetch_object($result1);
		
		if($row->avatar!=trim($avatar)){
			$query2  	  = "UPDATE $table_name SET avatar='$avatar' WHERE ID=".mysql_real_escape_string($user_id);	
			mysql_query($query2);
		}
	}
	public static function getUserName($user_id,$user_role=''){
		if($user_role=="guest"){
		
			$table_name	="guest";
		
		}else{
		
			$table_name	="users";
		}
		$query = "SELECT user_name FROM $table_name WHERE ID=".mysql_real_escape_string($user_id);
		$result = mysql_query($query);
		if($result){
			$row	=	mysql_fetch_object($result);
		}
		return $row->user_name;	
    }
	public static function parseString($str){
		$searcharray	= 	self::fetchAllSmiley();
		foreach($searcharray as $key=>$val){
			$str	=	str_replace($key,"<img src='smiley/".$val."' width='50px'>",$str);
		}
		return $str;
    }
	public static function getSmileys(){
		return self::$arr;
		
    }
	public static function deleteChat($id){
	
		$query = "DELETE FROM chat WHERE ID=".mysql_real_escape_string($id);
		if(mysql_query($query))
		return "1";
		else
		return "0";
	
	}
	public static function banUser($id,$role,$ban){
	
		if($role=='user')
			$table_name		=	"users";
		else 
			$table_name		=	"guest";
			
		echo $sql				=	"UPDATE $table_name set status=$ban WHERE ID=$id";
		mysql_query($sql);
	}
	public static function isBanUser($username,$role,$ip){
	
		if($role=='user')
			$table_name		=	"users";
		else 
			$table_name		=	"guest";
			
		$sql				=	"SELECT status FROM $table_name WHERE user_name='$username' AND ip='$ip'";
		$res				=	mysql_query($sql);
		$row				=	mysql_fetch_assoc($res);
		if($row['status']!=-1)
			return true;
		else 
			return false;
	}
	
	public static function fetchAllSmiley(){
	
		$table_name = "smiley";
		$sql 		= "SELECT *FROM $table_name";
		$result		=	mysql_query($sql);
		while($row  = mysql_fetch_array($result)){
			$results[$row['code']] = $row['image'];
		}
		return $results;
	
	}
	public static function updateTextColor($color){
		if($_SESSION['user']['id']=="" && $avatar=="")
		return;
		$user_id	=	$_SESSION['user']['id'];
		$role		=	$_SESSION['user']['role'];
		
		if($role=="guest")
		$table_name	=	"guest";
		else
		$table_name   = "users";
		
		$query  	  = "UPDATE $table_name SET text_color='$color' WHERE ID=".mysql_real_escape_string($user_id);	
		mysql_query($query);

	}
	public static function getUserTextColor($user_id,$role=''){
		if($role=="guest")
		$table_name	=	"guest";
		else
		$table_name = "users";
		
		$query 		= "SELECT text_color FROM $table_name WHERE ID=$user_id";
		$result     = mysql_query($query);
		if($result)
		$row		=	mysql_fetch_object($result);
		return $row->text_color;
    }

}
?>

ajax.php file to manage ajax requests

<?php
include_once '../config.php';
require "classes/chat-main.class.php";
if(!isset($_SESSION)){session_start();}
$response = array();

switch($_GET['action']){
		case 'saveChat':
		$user_name	    =	$_POST["user_name"];
		ChatMain::updateAvatar($_POST['url']);
		if($_SESSION["user"]["id"]==""){
			$val				=	(int)ChatMain::checkUserExists($user_name,$_POST['url']);
			if($val > 1){
				echo $id 		=	ChatMain::submitChat($_POST["chat_msg"],$_POST['group']);
			}
			else if($val==-1)
			echo "-1";
		}else{
			ChatMain::updateTextColor($_POST['color_code']);
			echo $id 			=	ChatMain::submitChat($_POST["chat_msg"],$_POST['group']);
		}
		break;
		case 'login':
		echo $id 	=	ChatMain::login($_POST["username"],$_POST["userpass"]);
		break;
		case 'signout':
		unset($_SESSION['user']);
		echo 1;
		break;
		case 'getAllChat':
		$numofNewMessage 	=	count(ChatMain::getAllChatMessages($_POST['group']))-$_POST["num"];
		$total				=	$numofNewMessage + (int)$_POST["num"];
		if($numofNewMessage>0){
			$allMessage			=	ChatMain::getChatMessages($numofNewMessage,$_POST['group']);
			 foreach($allMessage as $message){
			 ?>
		<div class="message">
          <table class="msg_table" border="0" width="100%">
            <tbody>
              <tr>
                <td scope="col" class="time"><?php echo date("h:i a",strtotime($message['create_date']));?><br/><?php echo date("m/d/Y",strtotime($message['create_date']));?></td>
                <td scope="col" class="user">
				<?php if($message['avatar']!=""){?>
						<img src="<?php echo $message['avatar'];?>" width="40px">
					<?php }else{?>
					<img src="img/default.jpg" width="40px">
					<?php }?>
			  </td>
                <td scope="col" class="user_name"><?php echo ChatMain::getUserName($message['author_id'],$message['author_role']);?></td>            
                <td scope="col" class="message_text"><?php echo $message['message'];?> </td>
              </tr>
            </tbody>
          </table>
        </div>
			<?php }?>
			<split>
			<?php 
			echo $total;
		}
		break;
		case 'deleteChat':
		$id	= base64_decode($_POST['id']);
		if(isset($_SESSION['user']['role']) && $_SESSION['user']['role']=='admin'){
			
			$val	=	ChatMain::deleteChat($id);
			echo $id;
		}
		
		break;
		case 'banUser':
			$id			= base64_decode($_POST['id']);
			$array		= explode("_",$id);	
			$user_id	= $array[0];
			$role		= $array[1];
		    $val		= ChatMain::banUser($user_id,$role,-1);
		break;
		case 'SignOut':
			unset($_SESSION['user']);
			echo "1";
		break;
		
	}

?>

config.php

<?php
error_reporting(E_ALL ^ E_NOTICE);
$link	=	mysql_connect('localhost','user_name','password');
mysql_select_db('database',$link);
?>

Leave a Reply