代码改变世界

使用PHP+MYSQL+JS实现聊天功能

2011-05-25 22:27  danhuang  阅读(1165)  评论(1编辑  收藏  举报
使用PHP+MYSQL+JS实现聊天功能
                                 ——by黄丹华Dayton
  其实为了实现这个聊天的功能我也是寻找了很多资料,实现这个聊天功能还是有很多缺陷,例如只能是一对一聊天,不能同时支持一个人对多个人聊天、不支持发送同样的消息,还有不支持的就是发送的第一个信息不能是1。下面我介绍一下我的实现方法,也希望更多的牛人能够给我指点迷津,让我们共同的把这个网页聊天功能实现的更强大,也可以作为开源代码给大家互相学习。
   首先介绍一下数据库,数据库有三个表是和这个功能实现有关的,一个是user,主要是存储用户的信息其中包含了用户的姓名、帐号、密码等信息。如下图:
包含的信息只是与接下来讲解的有关的属性。

第二表,这个表有四个属性,分别是id、userId、friendId、friendType。相信大家根据字面意思都能够明白表中的属性意思:下面是表的截图:


第三个表是我们的chating表,这个表就是用户与用户建立聊天的表,有如下属性:

 


这里我分成两个截图显示,其中的personId就是发起聊天的用户,friendId就是接受聊天的用户,contentToFriend就是person发送给friend的信息,而contentToperson就是friend发送给person的信息,其他的属性就无需讲解了。
   至此,如果大家想实现这个聊天功能的话,只需要建立这三个表就行了。下面我们开始讲解主题实现:
首先我们从数据层开始:数据层有三个类分别对应三个表,然后属性对应类中的相应的私有变量,然后有三个对应的数据库操作函数(删除、添加、根据属性获取id等等数据库操作函数)分别可以命名为,userFunction、friendListFunction、chatingFunction。
最后讲解我们的逻辑层实现,这是关键一步:这里会涉及六个文件。
chating_with_friend.php:
主要是显示出user的所有好友,例如如下代码:
  1. <ul>
  2.                                 <li><a href="#" onclick="displayfriend('one')">最近联系人</a></li>
  3.                                 <ul  class="dispalyfriend" id="one">
  4.                                 <a href="#" onclick="getbacknodisplay('one')">缩放</a>
  5.                 <?php
  6.                 foreach($friendList as $friend ){
  7.                         $friendType = $friend->get_friendType();
  8.                         $friendId = $friend->get_friendId();
  9.                         $user = get_user($friendId);
  10.                         $userName = $user->get_userName();
  11.                         if($friendType == 0){
  12.                                 ?>
  13.                                 <li><a href="#" onclick="connectFriend(<?php echo $friendId;?>,<?php echo $userId;?>,<?php echo $user->get_headPicture();?>)"><img style="width:20px" src="../imgs/headPicture/<?php echo $user->get_headPicture();?>.jpg"><?php echo $userName;?></a></li>
  14.                                 <?php
  15.                         }
  16.                 }
  17.                 ?>
  18.                                 </ul>
复制代码
这里只是显示所有的user的最近联系人的列表,关键就是遍历数据库查找所有为最近联系人的好友id,然后根据id得到user类,就可以显示所有信息。
其中

这段代码,显示用户,如果点击用户头像或者用户昵称,就会触发一个connectFriend函数,而且会传入三个参数分别是connectFriend(friendId,userId,headPicture),下面我们简单看一下这个函数,这个函数在chating.js文件中代码如下:
  1. function connectFriend(friendId,userId,headPicture){
  2.         deletenode();
  3.         //stopRefresh();
  4.         //clearTimeout(over);
  5.         $("chatingeare").style.display = "block";
  6.         $("friendId").value = friendId;
  7.         $("userId").value = userId;
  8.         $("headPicture").value = headPicture;
  9.         pushdown();
  10.         getmessage();
  11.         deletechating();
  12. }
复制代码
第一个deletenode()是一个函数:
  1. function deletenode(){
  2.         var a = document.getElementById("chatingtext");
  3.         var ul_arr = a.getElementsByTagName("p");
  4.         while(ul_arr.length!=0){
  5.                 a.removeChild(ul_arr[0]);
  6.         }
  7. }
复制代码
这个函数主要作用是清除上个与好友聊天的所有信息,因为我们的聊天主要是通过在id为chatingtext下插入<p></p>实现的,因此要清除之前的聊天记录只需要,使用DOM把他下面的所有子节点全部删除。

这段代码主要是当用户点击另外一个用户的时候会弹出对话框(对话框最初是隐藏的),对话框代码如下:
  1.         <div id="chatingeare" style="display:none;">
  2.                                 <div id="chatingtext">
  3.                                         <div id="refresh" class="node"></div>
  4.                                 </div>
  5.                                 <div>
  6.                                         <form>
  7.                                                 <textarea id="textarea" value=""></textarea><br/>
  8.                                                 <input type="button" onclick="sendmessage()" value="发送"/>
  9.                                                 <input id="friendId" type="hidden" value=""/><input id="userId" type="hidden" value=""/> <input id="headPicture" type="hidden" value=""/>
  10.                                                 <input type="button" onclick="nodisplay()" value="关闭"/>
  11.                                         </form>
  12.                                 </div>
  13.                         </div>
复制代码
这段代码,包含了三个hidden的type的input,主要是为了保存js中的变量值。

这段代码主要为了在js文件中互相传递参数,也就是说connectFriend(friendId,userId,headPicture)函数传入的三个参数,插入到html中input的value中,以后只要js希望得到这个参数就直接可以$(“friendId”).value就可以相应的得到friendId变量。其实这里的话可以设置全局变量,同样可以达到相应的结果。
接下来我们看pushdown函数,这个函数主要是为了,当用户正在和一个人聊天,而另外一个人却在Q用户的时候,用户可以把当前聊天的用户缩放到工具栏下,而切换与另外一个人聊天。代码如下:
  1. function pushdown(){
  2.         var headPicture = $("headPicture").value;
  3.         var friendId = $("friendId").value;
  4.         var userId = $("userId").value;
  5.         var len = $("newspicture").getElementsByTagName("input").length;
  6.         var count=0;
  7.         for(i=0;i<len;i++){
  8.                 if(friendId ==  $("newspicture").getElementsByTagName("input")[i].value)
  9.                         count++;
  10.         }
  11.         if(count==0){
  12.         res = "<li id='"+friendId+"'><a href='#'  onclick=connectFriend("+friendId+","+userId+","+headPicture+")>"+"<img style='width:20px' src =../imgs/headPicture/"+headPicture+".jpg />"+"</a>&nbsp;&nbsp;&nbsp;"+"<input name=headpicture value='"+friendId+"'type='hidden'></li>"
  13.         var newNode = document.createElement("span");
  14.         newNode.innerHTML = res;
  15.         $("newspicture").appendChild(newNode);
  16.         }
  17. }
复制代码
其中的前三行就是获取前面的三个变量,然后len是获取当前工具栏下的所有用户,主要是为了避免一个用户多次被缩放到工具栏下面,这里实现了一个判断,就是如果工具栏存在改用户,则不会插入用户头像,如果该工具栏下没有改用户则执行插入用户头像。
然后就是getmessage()函数:
  1. function getmessage(){
  2.         var friendId = $("friendId").value;
  3.         var userId = $("userId").value;
  4.         var url = "../ajax/getchating.php";
  5.         var myAjax = new Ajax.Request(
  6.         url,
  7.         {
  8.             method:"post",
  9.                          parameters: {
  10.                     friendId : friendId,
  11.                                         userId   : userId
  12.             },
  13.             onError: function (request){
  14.                 alert("请求方法发生错误!"+request.statusText);
  15.             },
  16.             onComplete: function (request){
  17.                 var res = request.responseText;
  18.                                 if(friendContext != res){
  19.                                         var newNode = document.createElement("p");
  20.                                         newNode.innerHTML = res;
  21.                                         newNode.className = "node";
  22.                                         $("chatingtext").appendChild(newNode);
  23.                                 }
  24.                                 friendContext = res;
  25.             },
  26.             asynchronous:true
  27.         });
  28.         t = setTimeout(getmessage,2000);
  29.         //addnewnode();
  30. }
复制代码
代码主要是通过ajax实现的,前面两行代码同样是获取userId、friendId变量。url主要是链接到相应的PHP处理文件,然后就是我们熟悉的ajax。接下来我们去查看一个getchating.php看一下主要是如何处理获取聊天信息功能的。
  1.     $friendId = $_POST['friendId'];
  2.         $userId = $_POST['userId'];
  3.     if (isset($friendId) && $friendId != 0 && isset($userId) && $userId != 0){
  4.                         if(exist_chating($userId, $friendId)){
  5.                                 $id = exist_chating($userId, $friendId);       
  6.                                 $user  = get_user($friendId);
  7.                                 $userName = $user->get_userName();
  8.                                 $chating = get_chating($id);
  9.                                 $contentToPerson = $chating->get_contentToPerson();
  10.                                 if($contentToPerson != 1){
  11.                                         echo "<span style='color:blue''>$userName:</span> $contentToPerson";
  12.                                 }
  13.                                 else
  14.                                         echo " ";
  15.                         }
  16.                         if(exist_chating($friendId,$userId)){
  17.                                 $id = exist_chating($friendId,$userId);       
  18.                                 $user  = get_user($friendId);
  19.                                 $userName = $user->get_userName();
  20.                                 $chating = get_chating($id);
  21.                                 $contentToPerson = $chating->get_contentToFriend();
  22.                                 if($contentToPerson != 1){
  23.                                         echo "<span style='color:blue''>$userName:</span> $contentToPerson";
  24.                                 }
  25.                                 else
  26.                                         echo " ";
  27.                         }
  28.                         else{
  29.                                 echo "";
  30.                         }
  31.         }
复制代码
前面两行代码是,获取ajax传入的两个变量,if条件主要是判断改id是否有效,如果就是主题代码:第一个条件判断该聊天是否已经建立,如果建立了,则直接返回用户输入的信息。第二个同样是判断是否已经建立。建立以后从数据库读取信息content,然后返回信息的html内容。Ajax得到返回的html代码,然后判断该代码是否和之前读取的代码相同,如果代码相同表示好友没有发送新消息给用户,那么我们在对话框中就不需要插入新的信息,如果不存在则插入本条返回的html信息,直接显示在对话框中。
  1.             onComplete: function (request){
  2.                 var res = request.responseText;
  3.                                 if(friendContext != res){
  4.                                         var newNode = document.createElement("p");
  5.                                         newNode.innerHTML = res;
  6.                                         newNode.className = "node";
  7.                                         $("chatingtext").appendChild(newNode);
  8.                                 }
  9.                                 friendContext = res;
  10.             },
复制代码
这段就是处理返回的结果代码,friendContext就是前一次获取的数据库中的好友信息。res就是获取的最新信息,如果两者不相同,则执行插入操作。如果两者相同则不需要做任何操作。
  1.         t = setTimeout(getmessage,2000);
复制代码
最后一段代码就是,每隔2秒钟获取数据库中的好友发给user的信息。
到这里为止我们就讲解了如何每隔2秒钟,获取是否有好友发送信息给自己。如果有就会插入在聊天对话框中,这样就可以实现,friend发送的消息,在本地可以实时的查看,而不需要刷新。
   接下来,我们讲解如何发送信息给好友:
  1.                                         <form>
  2.                                                 <textarea id="textarea" value=""></textarea><br/>
  3.                                                 <input type="button" onclick="sendmessage()" value="发送"/>
  4.                                                 <input id="friendId" type="hidden" value=""/><input id="userId" type="hidden" value=""/> <input id="headPicture" type="hidden" value=""/>
  5.                                                 <input type="button" onclick="nodisplay()" value="关闭"/>
  6.                                         </form>
复制代码
代码里面有一个发送的content和发送的用户,以及发送给谁的用户的value值,并且出了content其他的都是隐藏的,这个在前面的connectFriend函数里面已经讲解过,这里不在累赘。代码中的一个value值为“发送”的button,当用户点击发送的时候会触发sendmessage函数,下面我们来简单的看一下这个函数:
  1. function sendmessage(){
  2.         var friendId = $("friendId").value;
  3.         var userId = $("userId").value;
  4.         var content = $("textarea").value;
  5.         var url = "../ajax/chating.php";
  6.         var myAjax = new Ajax.Request(
  7.         url,
  8.         {
  9.             method:"post",
  10.                          parameters: {
  11.                     friendId : friendId,
  12.                                         userId   : userId,
  13.                                         content  : content
  14.             },
  15.             onError: function (request){
  16.                 alert("请求方法发生错误!"+request.statusText);
  17.             },
  18.             onComplete: function (request){
  19.                 var res = request.responseText;
  20.                 var newNode = document.createElement("p");
  21.                                 newNode.innerHTML = res;
  22.                                 newNode.className = "node";
  23.                                 $("chatingtext").appendChild(newNode);
  24.             },
  25.             asynchronous:true
  26.         });
  27.                 //t = setTimeout(getmessage, 5);
  28.                 //refresh(friendId,userId);
  29.                 //getmessage(friendId,userId);
  30. }
复制代码
前三行代码主要是获取三个变量值。url主要是链接处理文件PHP。接下来是Ajax,我们看一下chating.php处理的功能:
  1.     $friendId = $_POST['friendId'];
  2.         $userId = $_POST['userId'];
  3.         $content  = $_POST['content'];
  4.         $content = iconv('UTF-8','gb2312',$content);
  5.     if (isset($friendId) && $friendId != 0 && isset($userId) && $userId != 0){
  6.     if (exist_chating($userId, $friendId)) {       
  7.             $id =exist_chating($userId, $friendId);
  8.                 $user  = get_user($userId);
  9.                 $userName = $user->get_userName();
  10.                 update_contentToFriend($id, $content);
  11.                 $chating = get_chating($id);
  12.                 $contentToFriend = $chating->get_contentToFriend();
  13.                 echo "<span style='color:red'>$userName:</span> $contentToFriend";
  14.     }
  15.         else if(exist_chating($friendId,$userId )){
  16.                 $id =exist_chating($friendId,$userId );
  17.                 $user  = get_user($userId);
  18.                 $userName = $user->get_userName();
  19.                 update_contentToPerson($id, $content);
  20.                 $chating = get_chating($id);
  21.                 $contentToPerson= $chating->get_contentToPerson();
  22.                 echo "<span style='color:red'>$userName:</span> $contentToPerson";
  23.         }
  24.         else{
  25.                 $id = save_chating($userId, $friendId, $content, "1");
  26.                 $user  = get_user($userId);
  27.                 $userName = $user->get_userName();
  28.                 $chating = get_chating($id);
  29.                 $contentToFriend = $chating->get_contentToFriend();
  30.                 echo "<div><span style='color:red''>$userName:</span> $contentToFriend</div>";
  31.         }
复制代码
前四行是获取Ajax传入的三个变量,然后判断两个id是否合法。
接下来三个if判断函数,第一个判断当前是否已经在数据库建立了两者的聊天记录,第二个判断和第一个一样,主要是为了防止以下这种情况的发生:



其实这两者的关系是一样的,因此只需要存储一种,也就是先发起对话的人为user,回复信息的人为Friend。
如果数据库没有建立二者的聊天记录,在在数据库插入一段新的记录,并返回聊天信息。
  1.                         var newNode = document.createElement("p");
  2.                                         newNode.innerHTML = res;
  3.                                         newNode.className = "node";
  4.                                         $("chatingtext").appendChild(newNode);
复制代码
Ajax得到返回结果直接插入在html中,从而就可以实现,自己发送的消息自己可以查看。
  1. function bindUI(){
  2.         getothermessage();
  3. }
  4. function getothermessage(){
  5.         var userId = $("userId").value;
  6.         var url = "../ajax/getothermessage.php"
  7.         var myAjax = new Ajax.Request(
  8.         url,
  9.         {
  10.             method:"post",
  11.                          parameters: {
  12.                     userId:userId
  13.             },
  14.             onError: function (request){
  15.                 alert("请求方法发生错误!"+request.statusText);
  16.             },
  17.             onComplete: function (request){
  18.                 var res = request.responseText;
  19.                                 if(res.indexOf("newmessage") != -1){
  20.                                         play_click("../imgs/msg.wav");
  21.                                 }
  22.             },
  23.             asynchronous:true
  24.         });
  25. }
  26. function play_click(url){  
  27.     var div = $('music');  
  28.      div.innerHTML = '<embed src="'+url+'" loop="0" autostart="true" hidden="true"></embed>';  
  29.      var emb = document.getElementsByTagName('EMBED')[0];  
  30.      if (emb) {  
  31.         setTimeout(function(){div.innerHTML='';},1000);  
  32.     }  
  33. }
  34. document.observe('dom:loaded', bindUI);
复制代码

还有就是一些辅助的信息功能,比如说getothermessage(),就是获取当前正在和好友聊天,是否还有其他用户发送消息给我。Play_click()主要是声音提示,当有新的消息时候会有声音提示用户您有新的消息。
最后就是用户聊天结束以后,建立的聊天要从数据库删除,处理函数主要是:

deletechating.php同样的是PHP处理文件,主要是在数据库删除用户聊天记录。
大致的这样就可以实现一个简单的基本的聊天功能,我这里只是简单介绍了一下。我觉得自己介绍的也不是很详细,具体大家可以查看我下面的附件,其中包含这里面需要的六个文件,要运行的话,需要大家建立数据库。

代码下载