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

当MySQL表被修改(如添加行)时,如何在PHP中执行函数?

实时获取MySQL最新数据并更新页面的解决方案

以下是三种常用的实现方案,你可以根据自己的场景选择:

1. 短轮询(最简单的快速实现)

定时向服务器发送请求,检查是否有新数据,适合小流量场景。

前端代码(JavaScript)

// 每2秒发起一次请求
setInterval(() => {
    // 获取页面最后一条数据的ID(假设每条数据有唯一id字段)
    const lastId = document.querySelector('.message-item:last-child')?.dataset.id || 0;

    fetch(`get_new_data.php?last_id=${lastId}`)
        .then(res => res.json())
        .then(data => {
            if (data.length === 0) return;
            
            const container = document.getElementById('messages-container');
            data.forEach(item => {
                // 创建新消息元素并添加到页面
                const div = document.createElement('div');
                div.className = 'message-item';
                div.dataset.id = item.id;
                div.innerHTML = `<strong>${item.username}</strong>: ${item.content}`;
                container.appendChild(div);
                // 自动滚动到最新消息
                container.scrollTop = container.scrollHeight;
            });
        });
}, 2000);

后端代码(get_new_data.php)

<?php
// 替换为你的数据库连接信息
$conn = mysqli_connect('localhost', 'db_user', 'db_pass', 'db_name');
if (!$conn) exit(json_encode([]));

$lastId = isset($_GET['last_id']) ? intval($_GET['last_id']) : 0;

// 查询比lastId更大的新数据
$sql = "SELECT id, username, content FROM messages WHERE id > ? ORDER BY id ASC";
$stmt = mysqli_prepare($conn, $sql);
mysqli_stmt_bind_param($stmt, 'i', $lastId);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);

$newData = [];
while ($row = mysqli_fetch_assoc($result)) {
    $newData[] = $row;
}

echo json_encode($newData);
mysqli_close($conn);
?>

2. 长轮询(更高效的轮询方案)

前端发起请求后,服务器挂起连接,直到有新数据或超时才返回,减少无效请求次数。

前端代码(JavaScript)

function longPoll() {
    const lastId = document.querySelector('.message-item:last-child')?.dataset.id || 0;

    fetch(`long_poll.php?last_id=${lastId}`)
        .then(res => res.json())
        .then(data => {
            if (data.length > 0) {
                const container = document.getElementById('messages-container');
                data.forEach(item => {
                    const div = document.createElement('div');
                    div.className = 'message-item';
                    div.dataset.id = item.id;
                    div.innerHTML = `<strong>${item.username}</strong>: ${item.content}`;
                    container.appendChild(div);
                    container.scrollTop = container.scrollHeight;
                });
            }
            // 立即发起下一次请求
            longPoll();
        })
        .catch(() => {
            // 出错后延迟3秒重试
            setTimeout(longPoll, 3000);
        });
}

// 页面加载后启动长轮询
window.onload = longPoll;

后端代码(long_poll.php)

<?php
set_time_limit(60); // 设置超时时间为60秒
$conn = mysqli_connect('localhost', 'db_user', 'db_pass', 'db_name');
if (!$conn) exit(json_encode([]));

$lastId = isset($_GET['last_id']) ? intval($_GET['last_id']) : 0;

// 循环检测新数据
while (true) {
    $sql = "SELECT id, username, content FROM messages WHERE id > ? ORDER BY id ASC";
    $stmt = mysqli_prepare($conn, $sql);
    mysqli_stmt_bind_param($stmt, 'i', $lastId);
    mysqli_stmt_execute($stmt);
    $result = mysqli_stmt_get_result($stmt);

    $newData = [];
    while ($row = mysqli_fetch_assoc($result)) {
        $newData[] = $row;
    }

    if (!empty($newData)) {
        echo json_encode($newData);
        mysqli_close($conn);
        exit;
    }

    // 无新数据时休眠2秒再检测
    sleep(2);
}
?>

3. WebSocket(实时性最高的方案)

通过双向通信协议,服务器可以主动推送新数据给前端,适合高并发、低延迟场景,需要服务器支持WebSocket。

后端代码(基于Ratchet库)

先安装依赖:

composer require cboden/ratchet

创建WebSocket服务器(server.php):

<?php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
require 'vendor/autoload.php';

class MessagePusher implements MessageComponentInterface {
    protected $clients;
    protected $lastId;
    protected $dbConn;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
        // 连接数据库
        $this->dbConn = mysqli_connect('localhost', 'db_user', 'db_pass', 'db_name');
        // 获取当前最大消息ID
        $result = mysqli_query($this->dbConn, "SELECT MAX(id) as max_id FROM messages");
        $row = mysqli_fetch_assoc($result);
        $this->lastId = $row['max_id'] ?: 0;

        // 启动后台线程检测数据库更新
        $this->watchDb();
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
    }

    public function onMessage(ConnectionInterface $from, $msg) {
        // 处理前端发送的消息(比如新增消息到数据库)
        $data = json_decode($msg, true);
        if (isset($data['username'], $data['content'])) {
            $stmt = mysqli_prepare($this->dbConn, "INSERT INTO messages (username, content) VALUES (?, ?)");
            mysqli_stmt_bind_param($stmt, 'ss', $data['username'], $data['content']);
            mysqli_stmt_execute($stmt);
        }
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        $conn->close();
    }

    protected function watchDb() {
        while (true) {
            $result = mysqli_query($this->dbConn, "SELECT id, username, content FROM messages WHERE id > {$this->lastId} ORDER BY id ASC");
            $newData = [];
            while ($row = mysqli_fetch_assoc($result)) {
                $newData[] = $row;
                $this->lastId = $row['id'];
            }

            if (!empty($newData)) {
                // 推送给所有在线客户端
                foreach ($this->clients as $client) {
                    $client->send(json_encode($newData));
                }
            }

            sleep(1);
        }
    }
}

// 启动WebSocket服务器,监听8080端口
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new MessagePusher()
        )
    ),
    8080
);

$server->run();

前端代码(JavaScript)

// 连接WebSocket服务器
const ws = new WebSocket('ws://localhost:8080');

ws.onopen = () => console.log('WebSocket连接成功');

ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    const container = document.getElementById('messages-container');
    data.forEach(item => {
        const div = document.createElement('div');
        div.className = 'message-item';
        div.dataset.id = item.id;
        div.innerHTML = `<strong>${item.username}</strong>: ${item.content}`;
        container.appendChild(div);
        container.scrollTop = container.scrollHeight;
    });
};

ws.onerror = (err) => console.error('WebSocket错误:', err);

ws.onclose = () => {
    console.log('连接断开,3秒后重试');
    setTimeout(() => window.location.reload(), 3000);
};

// 发送消息的示例函数
function sendMsg() {
    const username = document.getElementById('username').value;
    const content = document.getElementById('content').value;
    ws.send(JSON.stringify({username, content}));
    document.getElementById('content').value = '';
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 12:48:22