PHP轮询实现
PHP 轮询实现方法
轮询(Polling)是一种客户端定期向服务器请求数据的技术,适用于需要实时更新但无法使用 WebSocket 或 SSE 的场景。以下是 PHP 中实现轮询的几种常见方法。
基础轮询实现
客户端通过 JavaScript 定时发送 AJAX 请求到 PHP 后端,PHP 返回最新数据。
客户端代码 (JavaScript):
function pollServer() {
fetch('poll.php')
.then(response => response.json())
.then(data => {
console.log('Received:', data);
setTimeout(pollServer, 3000); // 3秒后再次轮询
});
}
pollServer();
服务端代码 (poll.php):
<?php
header('Content-Type: application/json');
$latestData = ["time" => date("H:i:s"), "value" => rand(1, 100)];
echo json_encode($latestData);
?>
长轮询(Long Polling)
长轮询减少无效请求,服务器在有数据更新时才响应,否则保持连接。

客户端代码 (JavaScript):
function longPoll() {
fetch('longpoll.php')
.then(response => response.json())
.then(data => {
console.log('Update:', data);
longPoll(); // 立即发起下一次请求
});
}
longPoll();
服务端代码 (longpoll.php):
<?php
header('Content-Type: application/json');
$lastUpdate = $_GET['last'] ?? 0;
// 模拟等待数据更新(实际可能查询数据库)
while (true) {
$newData = checkForUpdates($lastUpdate);
if ($newData) {
echo json_encode($newData);
break;
}
sleep(1); // 避免CPU过载
}
function checkForUpdates($since) {
// 模拟数据变化
if (time() - $since > 2) {
return ["time" => date("H:i:s"), "id" => uniqid()];
}
return null;
}
?>
数据库驱动的轮询
适用于需要检查数据库更新的场景,如新消息通知。

服务端代码 (db_poll.php):
<?php
header('Content-Type: application/json');
$db = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$lastId = $_GET['last_id'] ?? 0;
$stmt = $db->prepare("SELECT * FROM messages WHERE id > ? ORDER BY id DESC LIMIT 1");
$stmt->execute([$lastId]);
$result = $stmt->fetch(PDO::FETCH_ASSOC);
if ($result) {
echo json_encode($result);
} else {
http_response_code(204); // No Content
}
?>
优化建议
- 设置合理的轮询间隔:避免过短(如500ms以下)导致服务器压力。
- 使用缓存:如 Redis 存储最新状态,减少数据库查询。
- 超时处理:客户端设置请求超时(如10秒),并重试机制。
- 退出条件:在不需要轮询时(如页面关闭)清除定时器。
完整示例:聊天应用轮询
客户端 (chat.js):
let lastMsgId = 0;
function fetchMessages() {
fetch(`get_messages.php?last_id=${lastMsgId}`)
.then(response => response.json())
.then(messages => {
if (messages.length > 0) {
lastMsgId = messages[messages.length-1].id;
// 渲染消息到界面
}
setTimeout(fetchMessages, 2000);
});
}
fetchMessages();
服务端 (get_messages.php):
<?php
header('Content-Type: application/json');
$lastId = (int)($_GET['last_id'] ?? 0);
$db = new PDO('mysql:host=localhost;dbname=chat', 'user', 'pass');
$stmt = $db->prepare("SELECT * FROM messages WHERE id > ? ORDER BY id ASC");
$stmt->execute([$lastId]);
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($messages);
?>
通过以上方法,可以实现从简单到复杂的轮询需求。对于更高实时性要求,建议考虑 WebSocket 或 Server-Sent Events (SSE)。






