如何创建一个简单的在线聊天工具
Chinese (Simplified) (中文(简体)) translation by Alfred Y. Zhu (you can also view the original English article)
在本教程中,我们将要使用PHP和jQuery创建一个简单的在线聊天工具。 这种实用性的模块对于你想要有实时在线客户支持系统的网站可以说是完美。
介绍


今天我们将要创建的这个聊天工具非常的简单, 它会包含一个登陆和登出的系统、AJAX功能特色、以及可以同时支持多个用户的功能。
步骤1:HTML结构代码
我们将由创建我们的第一个文件index.php来开始我们的教程。
1 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
2 |
<html xmlns="http://www.w3.org/1999/xhtml"> |
3 |
<head>
|
4 |
<title>Chat - Customer Module</title> |
5 |
<link type="text/css" rel="stylesheet" href="style.css" /> |
6 |
</head>
|
7 |
|
8 |
<div id="wrapper"> |
9 |
<div id="menu"> |
10 |
<p class="welcome">Welcome, <b></b></p> |
11 |
<p class="logout"><a id="exit" href="#">Exit Chat</a></p> |
12 |
<div style="clear:both"></div> |
13 |
</div>
|
14 |
|
15 |
<div id="chatbox"></div> |
16 |
|
17 |
<form name="message" action=""> |
18 |
<input name="usermsg" type="text" id="usermsg" size="63" /> |
19 |
<input name="submitmsg" type="submit" id="submitmsg" value="Send" /> |
20 |
</form>
|
21 |
</div>
|
22 |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> |
23 |
<script type="text/javascript"> |
24 |
// jQuery Document
|
25 |
$(document).ready(function(){ |
26 |
|
27 |
});
|
28 |
</script>
|
29 |
</body>
|
30 |
</html>
|
- 我们HTML的开始是正常的DOCTYPE,html,head和body标签, 在head标签中,我们添加了我们的标题,并且链接上CSS样式表(style.css)。
- 在body标签之内,我们将在叫#wrapper的div里面开始构建基本的结构, 我们将创建三个基本的部分:一个简单的菜单,我们的聊天框,以及消息的输入框;他们分别对应了一个div和id。
- 叫#menu的div是由两个段落元素组成的, 首先,我们要欢迎我们的用户,这个应该浮动在左侧,然后我们将要提供一个退出的链接,这个将浮动在右侧。 我们同时需要包含一个div来清除所有的元素。
- 叫#chatbox的div会囊括我们的聊天记录, 我们将要使用jQuery的ajax请求从一个外部文件读取我们的记录。
- 最后一个元素是我们的#wrapper div,这个将成为一个form,它将包括用户使用的文字输入框以及一个提交按钮。
- 我们在最后添加script脚本来使页面的读取更快。 首先我们将要链接到Google的jQuery CDS,因为我们将使用jQuery库来完成本教程。 我们的第二个script脚本标签将会是我们需要进行编辑的, 在整个文档准备就绪了(ready)以后我们再读取它。
步骤2:CSS样式
我们现在来添加一些CSS来让整个聊天系统比默认的浏览器样式看起来好看一点, 下面我们将要添加的代码是用在style.css文件里面的。
1 |
|
2 |
/* CSS Document */
|
3 |
body { |
4 |
font:12px arial; |
5 |
color: #222; |
6 |
text-align:center; |
7 |
padding:35px; } |
8 |
|
9 |
form, p, span { |
10 |
margin:0; |
11 |
padding:0; } |
12 |
|
13 |
input { font:12px arial; } |
14 |
|
15 |
a { |
16 |
color:#0000FF; |
17 |
text-decoration:none; } |
18 |
|
19 |
a:hover { text-decoration:underline; } |
20 |
|
21 |
#wrapper, #loginform { |
22 |
margin:0 auto; |
23 |
padding-bottom:25px; |
24 |
background:#EBF4FB; |
25 |
width:504px; |
26 |
border:1px solid #ACD8F0; } |
27 |
|
28 |
#loginform { padding-top:18px; } |
29 |
|
30 |
#loginform p { margin: 5px; } |
31 |
|
32 |
#chatbox { |
33 |
text-align:left; |
34 |
margin:0 auto; |
35 |
margin-bottom:25px; |
36 |
padding:10px; |
37 |
background:#fff; |
38 |
height:270px; |
39 |
width:430px; |
40 |
border:1px solid #ACD8F0; |
41 |
overflow:auto; } |
42 |
|
43 |
#usermsg { |
44 |
width:395px; |
45 |
border:1px solid #ACD8F0; } |
46 |
|
47 |
#submit { width: 60px; } |
48 |
|
49 |
.error { color: #ff0000; } |
50 |
|
51 |
#menu { padding:12.5px 25px 12.5px 25px; } |
52 |
|
53 |
.welcome { float:left; } |
54 |
|
55 |
.logout { float:right; } |
56 |
|
57 |
.msgln { margin:0 0 2px 0; } |
上面这些CSS没什么特别的,除了部分的id或者class,我们将要在之后再为它们添加。


你可以看到上面,我们已经完成了创建用户的聊天界面。
步骤3:使用PHP创建登录表单
现在我们将要放置一个简单的表单(form)来实现在用户进一步操作之前询问他们的名字。
1 |
<?
|
2 |
session_start(); |
3 |
|
4 |
function loginForm(){ |
5 |
echo' |
6 |
<div id="loginform">
|
7 |
<form action="index.php" method="post">
|
8 |
<p>Please enter your name to continue:</p>
|
9 |
<label for="name">Name:</label>
|
10 |
<input type="text" name="name" id="name" />
|
11 |
<input type="submit" name="enter" id="enter" value="Enter" />
|
12 |
</form>
|
13 |
</div>
|
14 |
'; |
15 |
}
|
16 |
|
17 |
if(isset($_POST['enter'])){ |
18 |
if($_POST['name'] != ""){ |
19 |
$_SESSION['name'] = stripslashes(htmlspecialchars($_POST['name'])); |
20 |
}
|
21 |
else{ |
22 |
echo '<span class="error">Please type in a name</span>'; |
23 |
}
|
24 |
}
|
25 |
?>
|
我们创建的这个loginForm()的function是由一个简单的登录表单组成的,它会询问用户的名字。 接下来,使用一个if和else的声明来验证这个人输入的名字。 如果一个用户输入了名字,我们将设置这个名字为$_SESSION['name']。 由于我们将使用基于cookie的session来存储名字,所以我们必须要在任何东西反馈到浏览器之前请求一个session_start()。
有一件事情你可能需要额外的注意一下,我们使用了htmlspecialchars() function,这个会转换特殊符号到HTML实体,以此来保护名字变量的字符不会成为跨站点脚本(XSS)的受害者。 我们将在之后同时添加这个功能到将要发布在聊天记录里面的文字变量上。
显示登录表单
如果用户并没有登录,并且还没有产生session,为了要显示登录的表单,我们需要在原始代码中的#wrapper div和script标签周围使用另外一个if和else的声明。 反之,如果用户已经登录而且已经有了一个session,这个声明将隐藏登录表单,并且显示聊天框。
1 |
<?php
|
2 |
if(!isset($_SESSION['name'])){ |
3 |
loginForm(); |
4 |
}
|
5 |
else{ |
6 |
?>
|
7 |
<div id="wrapper"> |
8 |
<div id="menu"> |
9 |
<p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p> |
10 |
<p class="logout"><a id="exit" href="#">Exit Chat</a></p> |
11 |
<div style="clear:both"></div> |
12 |
</div>
|
13 |
<div id="chatbox"></div> |
14 |
|
15 |
<form name="message" action=""> |
16 |
<input name="usermsg" type="text" id="usermsg" size="63" /> |
17 |
<input name="submitmsg" type="submit" id="submitmsg" value="Send" /> |
18 |
</form>
|
19 |
</div>
|
20 |
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script> |
21 |
<script type="text/javascript"> |
22 |
// jQuery Document
|
23 |
$(document).ready(function(){ |
24 |
});
|
25 |
</script>
|
26 |
<?php
|
27 |
}
|
28 |
?>
|


欢迎和登出菜单
我们还没有完成创建这个系统的登录部分, 因为我们还需要允许用户来登出,以结束聊天的session。 如果你还记得,我们原始的HTML结构包含了一个简单的菜单, 让我们回过头来添加一些PHP代码来给我们的菜单更多的功能。
首先,让我们添加用户名到欢迎的信息中, 我们将导出session中用户的名字来实现这个功能。
1 |
<p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p> |


为了允许用户登出并结束session,我们将要使用jQuery来完成它。
1 |
<script type="text/javascript"> |
2 |
// jQuery Document |
3 |
$(document).ready(function(){
|
4 |
//If user wants to end session |
5 |
$("#exit").click(function(){
|
6 |
var exit = confirm("Are you sure you want to end the session?");
|
7 |
if(exit==true){window.location = 'index.php?logout=true';}
|
8 |
}); |
9 |
}); |
10 |
</script> |
上面这段jQuery代码简单的展示了如果用户点击#exit链接的时候弹出的确认提示, 如果用户确认了退出,也就是说他们决定结束session,那么我们将把他们送回到index.php?logout=true。 这个简单的创建了一个叫logout并且值为true的变量。 我们将要使用PHP来抓住这个变量。


1 |
if(isset($_GET['logout'])){ |
2 |
|
3 |
//Simple exit message
|
4 |
$fp = fopen("log.html", 'a'); |
5 |
fwrite($fp, "<div class='msgln'><i>User ". $_SESSION['name'] ." has left the chat session.</i><br></div>"); |
6 |
fclose($fp); |
7 |
|
8 |
session_destroy(); |
9 |
header("Location: index.php"); //Redirect the user |
10 |
}
|
现在,我们使用isset()功能并检测是否得到一个logout的变量, 如果这个变量被一个url传递,例如上面我们制作的这个链接,我们将进行结束该用户名下session的操作。
在我们使用session_destroy()删除用户名字session之前,我们希望显示一个简单的退出消息到聊天记录里面。 它有可能说某某用户已经离开了聊天会话。 我们将使用fopen(),fwrite(),和fclose()功能来控制我们的log.html文件,这个被创建来作为我们的聊天记录的文件将在之后看到。 请注意,我们为div添加了一个‘msgIn'的class, 在之前我们已经为这个div定义过css了。
在完成这个之后,我们将删除session然后重定向用户到同样的页面但是登录表单将会显示。
步骤4:处理用户输入
在用户提交了表单以后,我们希望抓取他们的输入数据并且将它们写入到聊天记录里面, 要想完成这个,我们必须使用jQuery和PHP来同步客户端和服务器端的数据。
jQuery
几乎所有我们将使用jQuery来处理的数据都会循环围绕jQuery的POST请求。
1 |
//If user submits the form |
2 |
$("#submitmsg").click(function(){
|
3 |
var clientmsg = $("#usermsg").val();
|
4 |
$.post("post.php", {text: clientmsg});
|
5 |
$("#usermsg").attr("value", "");
|
6 |
return false; |
7 |
}); |
- 在我们做任何事情之前,我们必须先抓取用户的输入数据,或者说是他们所输入到#submitmsg input里面的文字。 这个可以使用val()功能来实现,它会抓取表单里面的所有数据。 我们将抓取的数据放入到clientmsg变量里面。
- 接下来是我们最重要的一个部分:jQuery POST 请求。 这一步会发送一个POST的请求到我们稍后会创建的post.php文件, 它会POST客户端的输入数据,或者任何已经被存储到clientmsg变量的数据。
- 在最后,我们将设置value属性的值到空白来清除#usermsg input。
注意,上面的这些代码将被放进我们的script标签,就是我们放置jQuery登出代码的地方。
PHP - post.php
现在,我们有了POST的数据,并且每一次当用户提交表单并发送一条新的消息的时候,数据们都被发送到了post.php文件里。 我们现在的目标就是抓取这些数据,然后回过头来写入到我们的聊天记录框里。
1 |
<?
|
2 |
session_start(); |
3 |
if(isset($_SESSION['name'])){ |
4 |
$text = $_POST['text']; |
5 |
|
6 |
$fp = fopen("log.html", 'a'); |
7 |
fwrite($fp, "<div class='msgln'>(".date("g:i A").") <b>".$_SESSION['name']."</b>: ".stripslashes(htmlspecialchars($text))."<br></div>"); |
8 |
fclose($fp); |
9 |
}
|
10 |
?>
|
- 在我们做任何事情之前,我们必须先用session_start()功能来开始post.php文件,因为我们也会在这个文件里面使用用户名字的session。
- 在做任何事情之前,我们需要使用isset布尔值,来检查如果session中’name'是否已经存在了。
- 现在我们将要抓取那些使用jQuery被发送到该文件的POST的数据, 并且我们将这些数据存储入$text变量。
- 这些所有的用户输入数据,都将被存储在log.html文件里。 为了完成这一步,我们将使用fopen功能的'a'模式打开文件,根据php.net的规则打开文件且仅限写入;接下来放置文件指示到文件的最后。 如果这个文件并不存在,那么尝试创建它。 接下来,我们使用fwrite()功能来写入我们的消息到这个文件里。
- 我们即将写入的消息将会被封闭在.msgIn div里面, 它会包含数据、使用date()功能所生成的时间、用户的session、以及内容等,同样的使用htmlspecialchars()功能来防止跨站点脚本XSS。
最后,我们使用fclose()来结束我们的文件操控。
步骤5:显示聊天记录(log.html) 内容
所有用户已经发布的消息都被处理过了,并且我们也是用jQuery将它们发布了;它们是被PHP写入到聊天记录框里面的, 所以唯一剩下来需要走的就是显示这些更新过的聊天记录给用户。
有些时候为了给自己省事,如果聊天文件里面已经有内容了的话,我们需要预先读取聊天记录到#chatbox div。
1 |
<div id="chatbox"><?php |
2 |
if(file_exists("log.html") && filesize("log.html") > 0){ |
3 |
$handle = fopen("log.html", "r"); |
4 |
$contents = fread($handle, filesize("log.html")); |
5 |
fclose($handle); |
6 |
|
7 |
echo $contents; |
8 |
}
|
9 |
?></div> |
由于我们使用过post.php,所以我们使用相似的规律,除了这一次我们只是读取并且输出这些文件的内容到页面上。
jQuery.ajax请求
ajax请求是我们做的所有事情的核心, 这个请求不仅仅允许我们在不刷新页面的情况下通过表单发送和接受数据,而且还允许我们处理数据请求。
1 |
//Load the file containing the chat log |
2 |
function loadLog(){
|
3 |
|
4 |
$.ajax({
|
5 |
url: "log.html", |
6 |
cache: false, |
7 |
success: function(html){
|
8 |
$("#chatbox").html(html); //Insert chat log into the #chatbox div
|
9 |
}, |
10 |
}); |
11 |
} |
我们将ajax的请求囊括在一个function里面, 过一会你就知道为什么了。 你可以看到,在上面,我们仅仅使用了3个jQuery ajax的请求对象。
- url: 一个URL请求的字符串 我们将使用我们的聊天记录文件名log.html。
- cache: 这个会避免我们的文件被放入缓存。 它会确保我们每一次发送请求的时候都会得到一个最新的聊天记录。
- success: 这个允许我们附上一个功能来传递我们请求的数据。
你可以看到,我们接着移动我们请求的数据(html)到#chatbox div。
自动滚动
由于你可能在别的聊天工具里面看过,如果聊天记录的容器(#chatbox)的内容溢出了就会自动的向下滚动。 我们将要实现一个简单的而又相似的效果,需要做的是在我们请求ajax的前后对比容器的滚动高度。 如果你滚动的高度大于请求之后的高度,我们会使用jQuery的动画效果来滚动#chatbox div。
1 |
//Load the file containing the chat log |
2 |
function loadLog(){
|
3 |
var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height before the request
|
4 |
$.ajax({
|
5 |
url: "log.html", |
6 |
cache: false, |
7 |
success: function(html){
|
8 |
$("#chatbox").html(html); //Insert chat log into the #chatbox div
|
9 |
|
10 |
//Auto-scroll |
11 |
var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height after the request
|
12 |
if(newscrollHeight > oldscrollHeight){
|
13 |
$("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div
|
14 |
} |
15 |
}, |
16 |
}); |
17 |
} |
- 在我们发送请求之前,首先我们将#chatbox div的混动高度存储在oldscrollHeight变量里
- 在我们请求成功返回以后,我们将#chatbox div的滚动高度存储到newscrollHeight变量中。
- 接下来我们使用一个if声明来比较两个滚动高度的变量, 如果newscrollHeight大于oldscrollHeight,我们使用动画效果来滚动#chatbox的div。
继续更新聊天记录
现在你可能会冒出来一个问题,我们将怎么才能一直的在用户来回更新数据时不断的更新数据呢? 或者换个方式来问这个问题,我们将如何不断的保持发送请求来更新数据呢?
1 |
setInterval (loadLog, 2500); //Reload file every 2500 ms or x ms if you wish to change the second parameter |
我们问题的回答你可以在setInterval function的那一行找到, 这个功能每2.5秒就会运行一次LoadLog() function,并且loadLog function会请求更新过的数据以及自动滚动的div。


搞定了
我们完成啦! 我希望你学到了该如何创建一个基本的聊天系统,而且如果你有任何的建议或者其他任何问题,我会很高兴在这里为你解答。 这个聊天系统是一个你可以很迅速拥有的简单聊天工具。 你可以渐渐的改进这个小程序并创建一个多人聊天室,添加管理性质的后端,添加表情符号等等。 天高任鸟飞!
如果你在想如何扩展这个聊天程序,下面是一些链接你可能希望去看一看:
- 使用表单键(Form Key)保护你的表单 - 防止XSS(跨站点脚本)以及防止伪造跨站点请求。
- 使用jQuery在提交表单的时候不需要刷新页面 - 扩展我们的ajax请求。
- 如何使用源生Javascript来制作AJAX请求 - 使用源生javascript来探究在幕后请求的工作是如何完成的。


- 你可以在Twitter上关注我们,或者订阅NETTUTS RSS推送来或缺更多每日互联网开发教程和文章。




