PHP 怎么推送数据到前端

wen PHP项目 4

本文目录导读:

PHP 怎么推送数据到前端

  1. 传统 HTTP 请求(最基础)
  2. SSE (Server-Sent Events) - 推荐
  3. WebSocket(双向通信)
  4. 使用 Laravel Echo(如果使用 Laravel)
  5. 使用第三方推送服务
  6. 实时消息中间件方案
  7. 最佳实践建议
  8. 完整示例:SSE 实现实时通知

在 PHP 中推送数据到前端有几种常见方式,主要取决于应用场景,以下是详细的解决方案:

传统 HTTP 请求(最基础)

AJAX 轮询

// frontend.js
setInterval(() => {
    fetch('/api/get-data')
        .then(res => res.json())
        .then(data => {
            updateUI(data);
        });
}, 3000);
// backend.php
header('Content-Type: application/json');
echo json_encode($data);

SSE (Server-Sent Events) - 推荐

SSE 是单向推送,服务器向客户端发送数据。

PHP 服务端实现

// sse.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
while (true) {
    $data = getNewData(); // 获取新数据
    echo "data: " . json_encode($data) . "\n\n";
    ob_flush();
    flush();
    sleep(2); // 每2秒推送一次
}

前端接收

// frontend.js
const eventSource = new EventSource('sse.php');
eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    updateUI(data);
};
eventSource.onerror = (error) => {
    console.error('SSE error:', error);
    eventSource.close();
};

WebSocket(双向通信)

需要安装 WebSocket 库,推荐使用 RatchetSwoole

使用 Ratchet 示例

composer require cboden/ratchet
// server.php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
class PushServer implements MessageComponentInterface {
    protected $clients;
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "New connection: {$conn->resourceId}\n";
    }
    public function onMessage(ConnectionInterface $from, $msg) {
        // 广播消息给所有客户端
        foreach ($this->clients as $client) {
            $client->send($msg);
        }
    }
    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "Error: {$e->getMessage()}\n";
        $conn->close();
    }
}
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new PushServer()
        )
    ),
    8080
);
echo "WebSocket server started\n";
$server->run();

前端 WebSocket 客户端

// frontend.js
const ws = new WebSocket('ws://localhost:8080');
ws.onopen = () => {
    console.log('WebSocket connection established');
};
ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    updateUI(data);
};
ws.onclose = () => {
    console.log('WebSocket connection closed');
};
// 发送消息
function sendMessage(message) {
    ws.send(JSON.stringify(message));
}

使用 Laravel Echo(如果使用 Laravel)

服务端配置

// config/broadcasting.php
'default' => env('BROADCAST_DRIVER', 'pusher'),
// .env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=your_app_id
PUSHER_APP_KEY=your_key
PUSHER_APP_SECRET=your_secret
PUSHER_APP_CLUSTER=mt1

发送事件

// Laravel Controller
broadcast(new NewOrderCreated($order));

前端订阅

// frontend.js
import Echo from "laravel-echo";
window.Pusher = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: process.env.MIX_PUSHER_APP_KEY,
    cluster: process.env.MIX_PUSHER_APP_CLUSTER,
    encrypted: true
});
// 监听事件
Echo.channel('orders')
    .listen('NewOrderCreated', (e) => {
        updateUI(e.order);
    });

使用第三方推送服务

使用 Firebase Cloud Messaging (FCM)

// send_push.php
require 'vendor/autoload.php';
use Kreait\Firebase\Factory;
$factory = (new Factory)
    ->withServiceAccount('path/to/firebase_credentials.json');
$messaging = $factory->createMessaging();
$message = [
    'notification' => [
        'title' => '新消息',
        'body' => '您有一条新通知',
    ],
    'topic' => 'news'
];
$messaging->send($message);

实时消息中间件方案

# 使用 Redis Pub/Sub
// publish.php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->publish('news', json_encode($data));
// subscribe.php
$redis->subscribe(['news'], function($redis, $channel, $message) {
    // 处理消息并推送
});

最佳实践建议

  1. 简单场景:使用 SSE,实现简单,自动重连
  2. 双向通信:使用 WebSocket
  3. 已用 Laravel:使用 Laravel Echo + Pusher
  4. 移动端:使用 FCM 或 APNs
  5. 高并发:考虑使用 Swoole 扩展

完整示例:SSE 实现实时通知

// notification_sse.php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // Nginx 禁用缓冲
$lastId = 0;
while (true) {
    $data = fetchNotifications($lastId);
    if ($data) {
        echo "id: {$lastId}\n";
        echo "event: notification\n";
        echo "data: " . json_encode($data) . "\n\n";
        ob_flush();
        flush();
    }
    usleep(500000); // 0.5秒
}

选择哪种方案取决于:

  • 实时性要求
  • 是否需要双向通信
  • 服务器资源
  • 开发复杂度
  • 浏览器兼容性要求

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