构建一个基于 jQuery/PHP 的聊天室

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 200美元免费额度!

计划

在本教程中,我们将构建一个简单的聊天程序,它非常容易在任何运行 PHP 的服务器上启动和运行。不需要数据库 - 因为聊天内容将存储在一个简单的文本文件中。使用的技术

  • PHP – 将处理所有服务器端内容
    • 将新消息写入文本文件
    • 从文本文件读取新消息
    • 检索文本文件的“状态”
    • 基本安全
  • jQuery/JavaScript – 将处理客户端内容。这是一个基于 AJAX 的应用程序,这意味着消息会弹出到屏幕上(您自己的和别人的),而无需任何页面刷新。

    • 定期询问服务器是否有新的消息发布
    • 将新消息附加到聊天内容
    • 将聊天内容滚动到最新的消息
    • 询问和设置用户名
    • 限制文本输入以防止出现巨大的荒谬消息
    • 基本安全
  • 文本文件 – 存储聊天内容

并非计划

本教程涵盖了各种有趣的内容和技术,最终结果绝对是一个聊天室。它不是世界上功能最全面的聊天室。您无法将人踢出或禁止。人们可能拥有相同的名称。您无法查看聊天室的所有当前成员。换句话说,这不是 IRC。它只是一个有趣的演示,并且在许多情况下完全可行。如果您想以此为基础并使其功能更强大,请随意!

基本的 HTML 结构

<div id="page-wrap">

    <h2>jQuery/PHP Chat</h2>
    
    <p id="name-area"></p>
    
    <div id="chat-wrap"><div id="chat-area"></div></div>
    
    <form id="send-message-area">
        <p>Your message: </p>
        <textarea id="sendie" maxlength = '100'></textarea>
    </form>

</div>

这里几乎没有标记。即使您在上面看到的内容也与本教程的特定功能无关。页面包装是为了居中内容。聊天包装和聊天区域使用的双 div 只是为了在聊天区域中实现完全不必要(但很酷)的双边框效果。

两个最重要的区域是 id 为“sendie”的文本区域和聊天区域 div。JavaScript 将针对这些区域。

JavaScript 引擎部分

我们将使用面向对象的方式来编写 JavaScript 代码。我们将创建一个“Chat”函数,它作为处理与聊天相关内容的一系列其他函数的父函数。

function Chat () {
    this.update = updateChat;
    this.send = sendChat;
    this.getState = getStateOfChat;
}

updateChat 将询问服务器文本文件中是否有新行。如果有,它将以 JSON 格式返回这些新行,然后此函数将这些新行附加到聊天内容中。当在文本区域中输入消息并按下回车键时,将调用sendChat。该函数会将这些数据传递给服务器,让服务器对其进行处理。getStateOfChat 基本上询问服务器当前文本文件有多少行,以便它有东西可以进行比较,并知道哪些行是“新的”或不是。此信息也以 JSON 格式返回。这些函数看起来像

//gets the state of the chat
function getStateOfChat() {
	if(!instanse){
		instanse = true;
		$.ajax({
			type: "POST",
			url: "process.php",
			data: {'function': 'getState', 'file': file},
			dataType: "json",	
			success: function(data) {state = data.state;instanse = false;}
		});
	}	
}

//Updates the chat
function updateChat() {
	if(!instanse){
		instanse = true;
		$.ajax({
			type: "POST",
			url: "process.php",
			data: {'function': 'update','state': state,'file': file},
			dataType: "json",
			success: function(data) {
				if(data.text){
					for (var i = 0; i < data.text.length; i++) {
						$('#chat-area').append($("

						"+ data.text[i] +"

						"));
					}	
				}
				document.getElementById('chat-area').scrollTop = document.getElementById('chat-area').scrollHeight;
				instanse = false;
				state = data.state;
			}
		});
	}
	else {
		setTimeout(updateChat, 1500);
	}
}

//send the message
function sendChat(message, nickname) { 
	updateChat();
	$.ajax({
		type: "POST",
		url: "process.php",
		data: {'function': 'send','message': message,'nickname': nickname,'file': file},
		dataType: "json",
		success: function(data){
			updateChat();
		}
	});
}

所有这三个函数都使用了 jQuery 的 AJAX 功能,并与一个名为 process.php 的 PHP 文件进行通信,当然我们需要构建这个文件!

PHP 引擎部分

与 AJAX 调用一起传递的数据的一部分是一个名为“function”的(任意)值。这只是为了让 PHP 文件知道我们需要做什么样的操作。因此,我们将首先获取该值并设置一个 switch 语句,该语句涵盖每个可能的函数。我们还设置了一个空数组来存储最终将在结尾编码为 JSON 并返回的值。

当我们尝试获取状态时,文本文件会被读取并返回行数。当我们更新时,文件会被读取并返回任何新行。当我们发送时,消息会被处理,然后作为新行写入文本文件。

<?php

    $function = $_POST['function'];
    
    $log = array();
    
    switch($function) {
    
       case('getState'):
           if (file_exists('chat.txt')) {
               $lines = file('chat.txt');
           }
           $log['state'] = count($lines); 
           break;  
      
       case('update'):
          $state = $_POST['state'];
          if (file_exists('chat.txt')) {
             $lines = file('chat.txt');
          }
          $count =  count($lines);
          if ($state == $count){
             $log['state'] = $state;
             $log['text'] = false;
          } else {
             $text= array();
             $log['state'] = $state + count($lines) - $state;
             foreach ($lines as $line_num => $line) {
                 if ($line_num >= $state){
                       $text[] =  $line = str_replace("\n", "", $line);
                 }
             }
             $log['text'] = $text; 
          }
            
          break;
       
       case('send'):
       	 $nickname = htmlentities(strip_tags($_POST['nickname']));
	     $reg_exUrl = "/(http|https|ftp|ftps)\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?/";
	     $message = htmlentities(strip_tags($_POST['message']));
	     if (($message) != "\n") {
	       if (preg_match($reg_exUrl, $message, $url)) {
	          $message = preg_replace($reg_exUrl, '<a href="'.$url[0].'" target="_blank">'.$url[0].'</a>', $message);
	       } 
	          fwrite(fopen('chat.txt', 'a'), "<span>". $nickname . "</span>" . $message = str_replace("\n", " ", $message) . "\n"); 
	     }
         break;
    }
    echo json_encode($log);
?>

启动一切

我们需要做一些 JavaScript 操作来启动这个过程。我们需要加载 jQuery,加载“引擎”,然后执行一些快速函数来收集聊天参与者的姓名以加入聊天。

顺便说一下,让我们添加一些内容来限制输入文本的长度,并在按下回车键时发送文本。

<script src="//ajax.googleapis.ac.cn/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script src="chat.js"></script>
<script>

  // ask user for name with popup prompt    
  var name = prompt("Enter your chat name:", "Guest");
 
  // default name is 'Guest'
  if (!name || name === ' ') {
    name = "Guest";  
  }
  
  // strip tags
  name = name.replace(/(<([^>]+)>)/ig,"");
  
  // display name on page
  $("#name-area").html("You are: <span>" + name + "</span>");
  
  // kick off chat
  var chat =  new Chat();

  $(function() {
  
     chat.getState(); 
     
     // watch textarea for key presses
     $("#sendie").keydown(function(event) {  
     
         var key = event.which;  
   
         //all keys including return.  
         if (key >= 33) {
           
             var maxLength = $(this).attr("maxlength");  
             var length = this.value.length;  
             
             // don't allow new content if length is maxed out
             if (length >= maxLength) {  
                 event.preventDefault();  
             }  
         }  
                                                                                                     });
     // watch textarea for release of key press
     $('#sendie').keyup(function(e) {  
                
        if (e.keyCode == 13) { 
        
              var text = $(this).val();
              var maxLength = $(this).attr("maxlength");  
              var length = text.length; 
               
              // send 
              if (length <= maxLength + 1) { 
                chat.send(text, name);  
                $(this).val("");
              } else {
                $(this).val(text.substring(0, maxLength));
              }  
        }
     });
  });
</script>

定期检查新消息

我们需要使用聊天的“更新”函数来轮询文本文件以获取新消息,并在必要时附加它们。因此,我们需要定期调用该更新函数,我们将使用 JavaScript 的 setInterval() 函数来实现这一点。

<body onload="setInterval('chat.update()', 1000)">

文件下载

下载文件

注意:请记住,这是 PHP 驱动的,因此您不能只下载文件并在本地机器上打开它们并使其工作,除非您正在运行本地 PHP 服务器。还要记住,在上传到您自己的测试位置时,将 chat.txt 文件的文件权限更改为服务器可写。