AJAX/PHP/MySQL实现数据库变更检测并提醒用户方案咨询
实现新订单实时提醒的可行方案
嘿,结合你现有的代码,我给你整理几个实用的方案来实现新订单提醒,从易到难,你可以根据自己的需求选:
方案1:短轮询(最简单,基于你现有代码改造)
这是最容易上手的方式,让前端定时发送请求去检查有没有新订单,完全兼容你现有的技术栈。
前端修改(JQuery)
把你现有的AJAX逻辑放到定时任务里,同时记录最后一次检查的时间,避免重复提醒:
// 记录最后一次检查到的订单时间,初始设为当前时间 let lastCheckTime = new Date().toISOString(); function checkNewOrders() { $.ajax({ type: "GET", dataType: 'json', // 改成JSON更方便处理数据 url: "check-orders.php", // 专门的订单检查接口 data: { last_check: lastCheckTime }, // 把最后检查时间传给后端 timeout: 30000, cache: false, // 禁用缓存,避免拿到旧数据 success: function(response) { if (response.new_count > 0) { // 有新订单,弹出提醒 alert(`${response.new_count} 个新订单已更新!`); // 更新最后检查时间为服务器返回的最新订单时间 lastCheckTime = response.latest_order_time; // 把新订单内容追加到页面指定区域 $('#changes').append(response.new_orders_html); } }, error: function(xhr, ajaxOptions, thrownError) { console.error('检查订单失败:', xhr.status, thrownError); }, complete: function() { // 请求完成后,间隔30秒再发起下一次检查(时间可以根据需求调整) setTimeout(checkNewOrders, 30000); } }); } // 页面加载完成后启动轮询 $(document).ready(function() { checkNewOrders(); });
后端修改(PHP)
新建check-orders.php,接收前端传的last_check参数,查询该时间之后的新订单:
<?php // 假设你已经有数据库连接$db $lastCheck = $_GET['last_check'] ?? date('Y-m-d H:i:s'); // 查询新订单 $stmt = $db->prepare("SELECT * FROM `orders` WHERE `date` > ? ORDER BY `date` DESC"); $stmt->execute([$lastCheck]); $newOrders = $stmt->fetchAll(PDO::FETCH_ASSOC); $newCount = count($newOrders); $latestTime = $lastCheck; if ($newCount > 0) { $latestTime = $newOrders[0]['date']; } // 生成新订单的HTML片段(可根据你的页面样式调整) $html = ''; foreach ($newOrders as $order) { $html .= "<div class='order-item'>订单ID: {$order['id']}, 创建时间: {$order['date']}</div>"; } // 返回JSON格式的响应 header('Content-Type: application/json'); echo json_encode([ 'new_count' => $newCount, 'latest_order_time' => $latestTime, 'new_orders_html' => $html ]); ?>
方案2:长轮询(更高效,减少无效请求)
短轮询会频繁发送无效请求,长轮询是让后端在没有新订单时保持连接,直到有新订单或者超时再返回,前端收到响应后立刻发起下一次请求,能大幅减少请求次数。
前端代码(JQuery)
和短轮询逻辑类似,但不需要定时,请求完成后立刻发起下一次:
let lastCheckTime = new Date().toISOString(); function longPollNewOrders() { $.ajax({ type: "GET", dataType: 'json', url: "long-poll-orders.php", data: { last_check: lastCheckTime }, timeout: 60000, // 超时设长一点,比如60秒 cache: false, success: function(response) { if (response.new_count > 0) { alert(`${response.new_count} 个新订单已更新!`); lastCheckTime = response.latest_order_time; $('#changes').append(response.new_orders_html); } // 不管有没有新订单,立刻发起下一次长轮询 longPollNewOrders(); }, error: function(xhr, ajaxOptions, thrownError) { console.error('长轮询失败:', xhr.status, thrownError); // 出错后间隔5秒再重试,避免频繁报错 setTimeout(longPollNewOrders, 5000); } }); } $(document).ready(function() { longPollNewOrders(); });
后端代码(PHP)
修改后端逻辑,循环检查新订单,直到有结果或者超时:
<?php set_time_limit(70); // 设置超时时间比前端多10秒 header('Content-Type: application/json'); $lastCheck = $_GET['last_check'] ?? date('Y-m-d H:i:s'); $timeout = 60; // 60秒超时 $startTime = time(); while (true) { // 检查是否超时 if (time() - $startTime > $timeout) { echo json_encode([ 'new_count' => 0, 'latest_order_time' => $lastCheck, 'new_orders_html' => '' ]); exit; } // 查询新订单 $stmt = $db->prepare("SELECT * FROM `orders` WHERE `date` > ? ORDER BY `date` DESC"); $stmt->execute([$lastCheck]); $newOrders = $stmt->fetchAll(PDO::FETCH_ASSOC); if (count($newOrders) > 0) { $latestTime = $newOrders[0]['date']; $html = ''; foreach ($newOrders as $order) { $html .= "<div class='order-item'>订单ID: {$order['id']}, 创建时间: {$order['date']}</div>"; } echo json_encode([ 'new_count' => count($newOrders), 'latest_order_time' => $latestTime, 'new_orders_html' => $html ]); exit; } // 没有新订单,休眠2秒再检查,减少数据库压力 sleep(2); } ?>
方案3:Server-Sent Events (SSE) 服务器推送
SSE是HTML5原生特性,专门用于服务器向客户端单向推送数据,比轮询更高效,实现也不算复杂。
前端代码(原生JS)
不需要JQuery,原生JS就能轻松实现:
// 建立SSE连接 const eventSource = new EventSource('sse-orders.php'); // 监听新订单事件 eventSource.addEventListener('new_order', function(event) { const data = JSON.parse(event.data); alert(`新订单提醒:订单ID ${data.id},创建时间 ${data.date}`); $('#changes').append(`<div class='order-item'>订单ID: ${data.id}, 创建时间: ${data.date}</div>`); }); // 监听连接错误 eventSource.addEventListener('error', function(event) { console.error('SSE连接出错:', event); // 连接断开后尝试重连 setTimeout(() => { window.location.reload(); // 或者重新创建EventSource实例 }, 5000); });
后端代码(PHP)
<?php header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); header('Connection: keep-alive'); header('Content-Encoding: none'); // 记录最后一次推送的订单ID $lastOrderId = 0; while (true) { // 查询最新的订单(比lastOrderId大的) $stmt = $db->prepare("SELECT * FROM `orders` WHERE `id` > ? ORDER BY `id` DESC LIMIT 1"); $stmt->execute([$lastOrderId]); $newOrder = $stmt->fetch(PDO::FETCH_ASSOC); if ($newOrder) { $lastOrderId = $newOrder['id']; // 发送新订单事件 echo "event: new_order\n"; echo "data: " . json_encode($newOrder) . "\n\n"; ob_flush(); flush(); } // 休眠3秒再检查 sleep(3); } ?>
内容的提问来源于stack exchange,提问作者TheOne
相关产品推荐
相关产品推荐

