You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需第三方服务,基于纯PHP和JS实现Web社交应用站内推送通知

Got it, let's build a pure PHP + JS (Comet-based) in-app notification system for your Facebook-like social app—no third-party services, no mobile/desktop notifications required. I’ll walk you through a working example using long polling (a common Comet technique) since it’s straightforward to implement with vanilla tools.

1. First: Database Setup

You’ll need a table to store notifications. Here’s a simple MySQL schema tailored for this use case:

CREATE TABLE notifications (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT NOT NULL, -- Links to your existing users table
    message VARCHAR(255) NOT NULL, -- e.g., "Sarah liked your post"
    is_read BOOLEAN DEFAULT FALSE, -- Track if the user has seen the notification
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
2. Backend PHP: Long Polling Endpoint

Create a file named notification_poll.php—this handles the long-lived connection from the frontend, waiting for new notifications to appear before sending a response.

<?php
// Start session to fetch the logged-in user's ID
session_start();
if (!isset($_SESSION['user_id'])) {
    http_response_code(401);
    exit('Unauthorized');
}
$user_id = $_SESSION['user_id'];

// Release the session lock immediately so other user requests don't hang
session_write_close();

// Set headers optimized for long polling
header('Content-Type: application/json');
header('Cache-Control: no-cache');
header('Connection: keep-alive');

// Poll for new notifications for up to 30 seconds before timing out
$timeout = 30;
$start_time = time();

while (time() - $start_time < $timeout) {
    // Connect to your database (replace with your credentials)
    $pdo = new PDO('mysql:host=localhost;dbname=your_app_db', 'db_user', 'db_password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Fetch unread notifications for the current user
    $stmt = $pdo->prepare("SELECT id, message, created_at FROM notifications WHERE user_id = ? AND is_read = FALSE ORDER BY created_at DESC");
    $stmt->execute([$user_id]);
    $notifications = $stmt->fetchAll(PDO::FETCH_ASSOC);

    if (!empty($notifications)) {
        // Optional: Mark notifications as read (you could also do this after frontend confirms)
        $stmt = $pdo->prepare("UPDATE notifications SET is_read = TRUE WHERE user_id = ? AND is_read = FALSE");
        $stmt->execute([$user_id]);
        
        echo json_encode($notifications);
        exit();
    }

    // Wait 2 seconds before polling again to reduce server load
    sleep(2);
}

// If no notifications found in the timeout window, return empty array
echo json_encode([]);
?>
3. Frontend JavaScript: Listen for Notifications

Add this script to your main app page (e.g., your dashboard template). It will repeatedly call the long polling endpoint and update the UI when new notifications arrive.

// Core function to handle long polling
function pollForNotifications() {
    fetch('notification_poll.php')
        .then(response => {
            if (!response.ok) throw new Error('Poll request failed');
            return response.json();
        })
        .then(notifications => {
            if (notifications.length > 0) {
                // Render new notifications in the UI
                displayNotifications(notifications);
            }
            // Restart polling immediately after the current request finishes
            setTimeout(pollForNotifications, 100);
        })
        .catch(error => {
            console.error('Polling error:', error);
            // Retry after 5 seconds if there's a network issue
            setTimeout(pollForNotifications, 5000);
        });
}

// Render notifications to the page
function displayNotifications(notifications) {
    const notificationContainer = document.getElementById('notification-container');
    const badge = document.getElementById('notification-badge');

    // Add each new notification to the top of the container
    notifications.forEach(notification => {
        const notificationEl = document.createElement('div');
        notificationEl.className = 'notification-item';
        notificationEl.innerHTML = `
            <p>${notification.message}</p>
            <small>${new Date(notification.created_at).toLocaleTimeString()}</small>
        `;
        notificationContainer.prepend(notificationEl);
    });

    // Update the unread count badge
    badge.textContent = parseInt(badge.textContent) + notifications.length;
}

// Start polling when the page loads
document.addEventListener('DOMContentLoaded', () => {
    pollForNotifications();
});

Add basic HTML to test the UI:

<div class="notification-wrapper">
    <button id="notification-button">🔔</button>
    <span id="notification-badge">0</span>
    <div id="notification-container"></div>
</div>

<style>
.notification-wrapper {
    position: relative;
    display: inline-block;
    margin: 20px;
}
#notification-badge {
    position: absolute;
    top: -8px;
    right: -8px;
    background: #ff4444;
    color: white;
    border-radius: 50%;
    padding: 2px 6px;
    font-size: 12px;
}
.notification-item {
    padding: 12px;
    border-bottom: 1px solid #eee;
    background: #f9f9f9;
    margin-top: 8px;
}
</style>
Key Tips for Optimization
  • Server Settings: Ensure PHP’s max_execution_time is set to at least 35 seconds (to cover the 30-second timeout + buffer). For Nginx/Apache, adjust connection timeout settings to avoid closing the long poll early.
  • Database Load: For high-traffic apps, replace MySQL polling with a memory store like Redis to track new notifications—it’s much faster than repeated database queries.
  • Read Status: Instead of marking notifications as read on the backend, you could add a separate endpoint (e.g., mark_notifications_read.php) that the frontend calls when the user opens the notification panel.

内容的提问来源于stack exchange,提问作者Bernard Gritsmiller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:46:11