本文目录导读:

这是一个非常经典且实用的PHP项目案例,实时聊天室是学习 PHP + Ajax + 数据库 + 长轮询/短轮询 之间协同工作的绝佳场景。
下面我为你提供一个轻量级、易于理解的聊天室实现方案,它基于短轮询(每隔一秒请求一次服务器),这是用纯Ajax实现“实时”感的最简单方式,适合初学者和中高级开发者重构。
项目结构
chatterbox/
├── index.php # 主页面 (HTML + CSS + JS)
├── send_message.php # 处理发送消息 (POST)
├── get_messages.php # 获取最新消息 (GET)
├── db.php # 数据库连接与初始化
└── schema.sql # 数据库建表语句
第一步:数据库设计 (MySQL)
创建一个简单的表来存储消息。
schema.sql
CREATE DATABASE IF NOT EXISTS chat_db;
USE chat_db;
CREATE TABLE IF NOT EXISTS messages (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
第二步:核心PHP文件
db.php (数据库连接)
<?php
$host = 'localhost';
$dbname = 'chat_db';
$username = 'root';
$password = '';
try {
$pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $username, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("连接失败: " . $e->getMessage());
}
?>
send_message.php (接收Ajax请求,写入数据库)
<?php
require_once 'db.php';
header('Content-Type: application/json');
// 获取POST数据
$username = trim($_POST['username'] ?? '');
$message = trim($_POST['message'] ?? '');
// 简单验证
if (empty($username) || empty($message)) {
echo json_encode(['success' => false, 'error' => '用户名或消息不能为空']);
exit;
}
// 防止XSS (将在前端进行,但后端也要做)
$username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8');
$message = htmlspecialchars($message, ENT_QUOTES, 'UTF-8');
// 插入数据库
$stmt = $pdo->prepare("INSERT INTO messages (username, message) VALUES (?, ?)");
$success = $stmt->execute([$username, $message]);
echo json_encode(['success' => $success]);
?>
get_messages.php (获取新消息,Ajax轮询的目标)
核心逻辑: 它接收一个 last_id 参数(上一次请求拿到的最后一条消息ID),然后只返回ID大于该值的新消息。
<?php
require_once 'db.php';
header('Content-Type: application/json');
// 获取客户端传来的最后一条消息ID,若没有则从0开始
$last_id = isset($_GET['last_id']) ? (int)$_GET['last_id'] : 0;
// 获取比 last_id 更新的消息,限制20条防止数据爆炸
$stmt = $pdo->prepare("SELECT id, username, message, created_at FROM messages WHERE id > ? ORDER BY id ASC LIMIT 20");
$stmt->execute([$last_id]);
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['messages' => $messages, 'last_id' => $last_id]);
?>
第三步:前端代码 (index.php)
这是核心,包含HTML结构、CSS样式和Ajax逻辑。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">PHP Ajax 实时聊天室</title>
<style>
#chat-box {
width: 400px; height: 350px; border: 1px solid #ccc;
overflow-y: auto; padding: 10px; margin-bottom: 10px;
background-color: #f9f9f9;
}
.msg { margin-bottom: 8px; }
.msg .user { font-weight: bold; color: #007bff; }
.msg .time { font-size: 0.8em; color: #888; margin-left: 10px; }
#username-input, #message-input { padding: 5px; width: 100%; box-sizing: border-box; margin-bottom: 5px; }
#send-btn { padding: 7px 20px; background-color: #007bff; color: white; border: none; cursor: pointer; }
#send-btn:hover { background-color: #0056b3; }
</style>
</head>
<body>
<h1>PHP + Ajax 实时聊天</h1>
<div id="chat-box"></div>
<input type="text" id="username-input" placeholder="输入你的名字" value="User<?php echo rand(100,999); ?>" />
<input type="text" id="message-input" placeholder="输入消息..." onkeydown="if(event.key === 'Enter') sendMessage();" />
<button id="send-btn" onclick="sendMessage()">发送</button>
<script>
let lastMessageId = 0; // 记录最后一条消息ID
const chatBox = document.getElementById('chat-box');
// ---------- 1. 发送消息 (Ajax POST) ----------
function sendMessage() {
const username = document.getElementById('username-input').value.trim();
const message = document.getElementById('message-input').value.trim();
if (!message || !username) {
alert('用户名和消息不能为空');
return;
}
const xhr = new XMLHttpRequest();
xhr.open('POST', 'send_message.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
if (response.success) {
document.getElementById('message-input').value = ''; // 清空输入框
// 立即请求新消息,加速显示
fetchMessages();
} else {
alert('发送失败: ' + response.error);
}
}
};
xhr.send(`username=${encodeURIComponent(username)}&message=${encodeURIComponent(message)}`);
}
// ---------- 2. 获取新消息 (Ajax GET 轮询) ----------
function fetchMessages() {
const xhr = new XMLHttpRequest();
// 关键:把 lastMessageId 传给服务器
xhr.open('GET', `get_messages.php?last_id=${lastMessageId}`, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
const response = JSON.parse(xhr.responseText);
if (response.messages && response.messages.length > 0) {
// 更新last_id
const lastMsg = response.messages[response.messages.length - 1];
lastMessageId = lastMsg.id;
// 渲染新消息
for (const msg of response.messages) {
appendMessage(msg);
}
}
}
};
xhr.send();
}
// ---------- 3. 将消息追加到聊天框 ----------
function appendMessage(msg) {
const div = document.createElement('div');
div.className = 'msg';
div.innerHTML = `
<span class="user">${escapeHtml(msg.username)}</span>
<span class="time">${msg.created_at}</span>
<br/>
<span class="content">${escapeHtml(msg.message)}</span>
`;
chatBox.appendChild(div);
// 自动滚动到底部
chatBox.scrollTop = chatBox.scrollHeight;
}
// ---------- 4. 简单的XSS防护 (前端) ----------
function escapeHtml(text) {
const div = document.createElement('div');
div.appendChild(document.createTextNode(text));
return div.innerHTML;
}
// ---------- 5. 启动轮询 (每1秒请求一次) ----------
// 页面加载后立即请求一次,并开始定时器
setInterval(fetchMessages, 1000); // 1秒一次
// 可选:页面加载时立即拉取历史消息(last_id=0)
window.onload = function() {
fetchMessages();
};
</script>
</body>
</html>
第四步:运行测试
- 将上述4个文件放在你的Web服务器目录下(如
xampp/htdocs/chatterbox/)。 - 通过phpMyAdmin或命令行执行
schema.sql创建数据库和表。 - 打开浏览器访问
http://localhost/chatterbox/index.php。 - 打开两个不同的浏览器窗口或标签页(使用不同的用户名),开始聊天吧!
| 概念 | 在本项目中的体现 |
|---|---|
| 短轮询 | 前端 setInterval(fetchMessages, 1000) 每秒发一次请求。 |
| 增量加载 | get_messages.php 根据 last_id 只返回新消息,避免重复加载。 |
| 无刷新发送 | sendMessage() 使用 XMLHttpRequest 异步发送,页面不刷新。 |
| 安全问题 | 后端使用 htmlspecialchars,前端使用 createTextNode 防止XSS。 |
| 数据库 | 使用 PDO 和预处理语句防止SQL注入。 |
进阶建议(如果你想挑战一下)
- 升级为长轮询(Long Polling):修改
get_messages.php,如果没有新消息,不要立刻返回空数组,而是sleep(1)循环等待,直到有消息或超时(如30秒)。 - 引入WebSocket:使用
Ratchet(PHP WebSocket库) 实现真正的实时推送。 - 使用Node.js:如果项目要求高并发实时性,通常Node.js比PHP更适合,但上述Ajax方案在中小流量下完全够用。
这个项目案例涵盖了Web开发中非常核心的异步交互模式,希望对你有所帮助!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播