PHP项目怎样实现公告弹窗推送?

wen PHP项目 16

本文目录导读:

PHP项目怎样实现公告弹窗推送?

  1. 方案一:传统后端渲染(适用于“登录后或刷新后才显示”)
  2. 方案二:轮询(Ajax 短轮询,适用于“几分钟内看到就行”)
  3. 方案三:Server-Sent Events(SSE,单向实时推送,推荐
  4. 方案四:WebSocket(双向实时,大规模推送)
  5. 综合建议

在 PHP 项目中实现公告弹窗推送,通常有几种主流方案,具体取决于你的实时性要求用户群规模以及技术栈

以下是几种由简到繁、由传统到实时的实现方案:

传统后端渲染(适用于“登录后或刷新后才显示”)

这是最基础、最稳定的方式,用户每次刷新页面或跳转后,PHP后端将公告数据嵌入到前端HTML中,由JavaScript控制弹窗。

流程:

  1. 后端 (PHP): 在控制器中从数据库读取未过期、有效的公告。
  2. 前端 (JS): 判断是否有公告数据,有则弹窗。

代码示例:

// controller.php (后端)
<?php
// 假设从数据库查询最新的一条公告
$notice = $db->query("SELECT * FROM notices WHERE status=1 AND expire_time > NOW() ORDER BY create_time DESC LIMIT 1")->fetch();
// 将公告数据传递给前端视图
$data['notice'] = $notice; // 比如是 ['title'=>'系统维护', 'content'=>'今晚2点...', 'type'=>'info']
// 加载视图并输出
?>
<!-- view.html (前端,混合PHP) -->
<?php if ($notice): ?>
<script>
    window.addEventListener('load', function() {
        // 使用 SweetAlert2 或 Bootstrap Modal
        Swal.fire({
            title: '<?php echo addslashes($notice['title']); ?>',
            html: '<?php echo addslashes(nl2br($notice['content'])); ?>',
            icon: '<?php echo $notice['type']; ?>', // 'info', 'warning', 'error'
            confirmButtonText: '我已阅读'
        });
    });
</script>
<?php endif; ?>

优点: 实现简单,兼容性好。 缺点: 用户不刷新页面就看不到新公告。


轮询(Ajax 短轮询,适用于“几分钟内看到就行”)

定时(如每30秒)向服务器发送请求,查询是否有新公告。

流程:

  1. 前端 JS 设置定时器 (setInterval)。
  2. 每次请求一个 PHP 接口,携带上次接收的公告 ID 或时间戳。
  3. PHP 查询有无更新的公告,返回 JSON。
  4. 前端判断是否弹窗。

代码示例:

// 前端 JS (例如用 jQuery)
let lastNoticeId = 0; // 从 cookie 或 session 中读取
let lastCheckTime = Date.now();
function checkNotice() {
    fetch(`/api/check-notice?last_id=${lastNoticeId}&time=${lastCheckTime}`)
        .then(res => res.json())
        .then(data => {
            if (data.has_new) {
                // 更新记录
                lastNoticeId = data.notice.id;
                // 弹出公告 (使用方案一的弹窗代码)
                showNotice(data.notice);
            }
        });
}
// 每隔 30 秒检查一次
setInterval(checkNotice, 30000);
checkNotice(); // 页面加载立即检查一次
// api/check-notice.php (后端 PHP)
<?php
header('Content-Type: application/json');
$lastId = intval($_GET['last_id'] ?? 0);
// 查询比 lastId 更新的公告
$notice = $db->query("SELECT * FROM notices WHERE id > {$lastId} AND status=1 AND expire_time > NOW() ORDER BY id ASC LIMIT 1")->fetch();
if ($notice) {
    echo json_encode([
        'has_new' => true,
        'notice' => $notice
    ]);
} else {
    echo json_encode(['has_new' => false]);
}

优点: 能实现准实时,不依赖复杂技术。 缺点: 有请求消耗,延迟取决于轮询间隔,高并发时对服务器压力较大。


Server-Sent Events(SSE,单向实时推送,推荐

SSE 是 HTML5 规范,允许服务器主动向浏览器推送数据。特别适合“公告推送”这种服务器到客户端的单向场景

流程:

  1. 前端创建 EventSource 对象,连接一个 PHP 文件。
  2. PHP 文件保持连接不断开(set_time_limit(0)),循环检查数据库。
  3. 有数据时,echo "data: ...\n\n" 推送给前端。

前端 JS:

// 连接到 SSE 端点
const eventSource = new EventSource('/api/notice-stream');
// 接收消息
eventSource.onmessage = function(event) {
    const notice = JSON.parse(event.data);
    showNotice(notice); // 弹窗
};
eventSource.onerror = function(err) {
    console.error('SSE 连接错误,将在几秒后重连', err);
};

后端 PHP(/api/notice-stream):

<?php
// 设置 SSE 头
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
// 关闭执行时间限制
set_time_limit(0);
// 获取用户上次看到的公告 ID (从 session 或请求参数)
session_start();
$lastNoticeId = $_SESSION['last_notice_id'] ?? 0;
while (true) {
    // 查询是否有新公告
    $notice = $db->query("SELECT * FROM notices WHERE id > {$lastNoticeId} AND status=1 AND expire_time > NOW() ORDER BY id ASC LIMIT 1")->fetch();
    if ($notice) {
        // 发送数据
        echo "data: " . json_encode($notice) . "\n\n";
        ob_flush();
        flush();
        // 更新最后 ID
        $lastNoticeId = $notice['id'];
        $_SESSION['last_notice_id'] = $lastNoticeId;
    }
    // 没有新公告,等待几秒再查
    sleep(5);
}

优点: 原生支持,实现简单,不需要 WebSocket 复杂协议,自动重连。 缺点: 仅支持单向(服务器→客户端);不适合非常高频的推送(如1秒1次)。


WebSocket(双向实时,大规模推送)

如果你的项目已经引入了 Laravel + Websocket(如 Pusher, Swoole) 或使用 Workerman,这是最强大的方案。

概览:

  1. 管理员后台发布公告。
  2. PHP 触发事件(如 broadcast(new NoticePushed($notice)))。
  3. WebSocket 服务广播消息给所有或特定房间的客户端。
  4. 前端收到消息后弹窗。

适用场景:

  • 已有 WebSocket 基础设施。
  • 需要同时处理聊天、通知、消息等实时功能。
  • 用户量非常大,需要高效的广播。

优点: 实时性最高,双向通信。 缺点: 开发成本高,需要部署 WebSocket 服务(如 Node.js + Socket.io 或 PHP Swoole)。


综合建议

场景 推荐方案
小型项目,刷新生效即可 后端渲染 + 弹窗
中型项目,需要几分钟内看到 Ajax 轮询
公告相对重要,希望用户一来就看到更新 SSE(性价比最高)
高并发 / 有实时通信基础设施 WebSocket

额外细节:

  • 存储已读状态:对于公告,通常建议记录用户是否已读,可以在 user_notice_log 表中记录 (user_id, notice_id, read_time),避免重复弹窗。
  • 弹窗UI:推荐使用 SweetAlert2Bootstrap Modal,看起来专业且兼容性好。
  • 公告权限:区分“全部用户”、“指定用户组”、“指定部门”,推送时根据条件过滤。
  • 注意:如果使用 SSE 或 WebSocket,在压力测试时需关注 PHP 的 max_children(进程数)和内存限制,因为每个连接都会占用一个 PHP 进程。

对于典型的 PHP 项目(如 CMS、OA、ERP),方案三(SSE) 是最推荐的,平衡了实时性、开发成本和服务器压力。

抱歉,评论功能暂时关闭!