技术问询:在JS中嵌套PHP,用xmlhttp、toastr实现MySQL消息全员推送
Hey Zac, let's break down how to refine your real-time message display setup with XMLHTTP, toastr, PHP, and MySQL—here's a step-by-step guide to make it more robust, secure, and user-friendly:
Your current fixed 5-second interval can lead to overlapping requests if a query takes longer than expected. Instead, trigger the next poll only after the previous request completes to avoid server overload. Also, avoid passing the username in the URL (it’s vulnerable to tampering)—let the backend pull it directly from the session.
Here's improved frontend code (using native XMLHTTP; we can also use jQuery for cleaner syntax):
function fetchNewMessages() { const xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState === 4) { if (this.status === 200) { try { const response = JSON.parse(this.responseText); // Show toastr for each new message if (response.messages.length > 0) { response.messages.forEach(msg => { $.toast({ heading: msg.title, text: msg.message, position: 'top-right', // Customize position as needed showHideTransition: 'slide', icon: 'info', // Use 'error'/'success' for different message types hideAfter: 5000 // Auto-hide after 5 seconds }); }); } } catch (e) { console.error('Failed to parse response:', e); } } else { console.error('Request failed with status:', this.status); } // Schedule next poll only after this request finishes setTimeout(fetchNewMessages, 5000); } }; xmlhttp.open("GET", "includes/ajax/user/general/messages.php", true); xmlhttp.send(); } // Start the polling loop on page load window.onload = fetchNewMessages;
Your messages.php needs to handle SQL injection, mark messages as read to avoid duplicate popups, and return structured JSON. Here's a secure implementation:
<?php session_start(); // Block unauthenticated users if (!isset($_SESSION['username'])) { echo json_encode(['messages' => []]); exit; } $username = $_SESSION['username']; // Connect to MySQL (use mysqli or PDO for prepared statements) $conn = mysqli_connect("localhost", "your_db_user", "your_db_pass", "your_db_name"); if (!$conn) { error_log("Database connection failed: " . mysqli_connect_error()); echo json_encode(['messages' => []]); exit; } // Fetch unread messages using prepared statements (prevents SQL injection) $stmt = $conn->prepare("SELECT id, title, message FROM messages WHERE recipient = ? AND is_read = 0"); $stmt->bind_param("s", $username); $stmt->execute(); $result = $stmt->get_result(); $messages = []; while ($row = $result->fetch_assoc()) { $messages[] = $row; // Mark message as read to avoid re-showing it $updateStmt = $conn->prepare("UPDATE messages SET is_read = 1 WHERE id = ?"); $updateStmt->bind_param("i", $row['id']); $updateStmt->execute(); $updateStmt->close(); } $stmt->close(); mysqli_close($conn); // Return JSON response header('Content-Type: application/json'); echo json_encode(['messages' => $messages]); ?>
Key notes here:
- Use prepared statements to eliminate SQL injection risks.
- Mark messages as
is_readonce fetched so users don't see duplicates. - Add error logging for debugging, and always return valid JSON even if something fails.
Make sure you've properly included toastr's dependencies first:
<!-- Include jQuery first --> <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> <!-- Toastr CSS & JS --> <link rel="stylesheet" href="path/to/toastr.css"> <script src="path/to/toastr.min.js"></script>
Customize toastr behavior to fit your needs:
- Use different
iconvalues (info,success,warning,error) to match message types. - Adjust
hideAfterto control how long popups stay visible (set tofalseto keep them until manually closed). - Use
positionto place popups where they won't block important content (e.g.,top-center,bottom-right).
If you expect a lot of users, short polling (every 5 seconds) can strain your server. Consider these upgrades:
- Long Polling (Comet): Keep the HTTP connection open until new messages are available, then immediately re-establish it. This reduces unnecessary requests.
- WebSocket: Use a library like Ratchet for PHP to implement real-time, bidirectional communication. The server pushes messages to clients instantly, no polling needed.
- Frontend Message Caching: Store IDs of displayed messages in
localStorageas an extra layer of protection against duplicates.
内容的提问来源于stack exchange,提问作者Zac Ram

