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

如何用Laravel与Next.js实现两个独立前端的实时动作同步?

Laravel + 双Next.js前端实时订单同步最佳方案实现

在你的Laravel后端+双独立Next.js前端架构下,Laravel Echo + WebSockets是实现订单实时同步的最优方案。理由如下:

  • 和Laravel深度集成,开发成本低,代码侵入性小
  • 支持双向实时通信,既能推送新订单给管理员,后续扩展管理员操作通知客户也无压力
  • 相比其他方案(如Webhooks、消息中间件),更贴合中小规模订单同步场景,无需额外复杂的基础设施维护

一、方案选型对比(针对你列出的选项)

  • REST API+Webhooks:异步通知存在延迟,且管理员前端需暴露公网接收Webhook,部署复杂度高,不适合实时需求
  • 消息中间件(RabbitMQ/Kafka):适合高并发海量消息场景,但对于普通订单同步来说过于笨重,学习和维护成本高
  • GraphQL订阅:需要额外搭建GraphQL服务,若现有系统是REST API,改造成本大
  • SSE:仅支持服务器单向推送,后续扩展双向交互能力受限
  • WebSockets(Laravel Echo):完美匹配实时订单推送需求,和现有技术栈兼容性拉满,开发效率高

二、Laravel后端实现步骤

1. 安装依赖与配置

# 后端安装Pusher SDK
composer require pusher/pusher-php-server
# 前端(两个Next.js项目都需要)安装Echo和Pusher客户端
npm install laravel-echo pusher-js

修改.env配置(如果用自建WebSocket服务器,后续替换为Laravel WebSockets地址):

BROADCAST_DRIVER=pusher
PUSHER_APP_ID=你的应用ID
PUSHER_APP_KEY=你的应用KEY
PUSHER_APP_SECRET=你的应用SECRET
PUSHER_HOST=localhost # 用Laravel WebSockets时填这个,否则填Pusher官方地址
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1

2. 创建订单广播事件

生成事件文件:

php artisan make:event OrderCreated

编辑app/Events/OrderCreated.php:

<?php

namespace App\Events;

use App\Models\Order;
use Illuminate\Broadcasting\Channel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class OrderCreated implements ShouldBroadcast
{
    use Dispatchable, SerializesModels;

    public $order;

    public function __construct(Order $order)
    {
        $this->order = $order;
    }

    // 指定管理员前端订阅的频道
    public function broadcastOn()
    {
        return new Channel('admin.orders');
    }

    // 自定义事件名称,方便前端精准监听
    public function broadcastAs()
    {
        return 'order.created';
    }
}

3. 在订单创建逻辑中触发事件

在订单控制器的store方法里添加广播触发:

public function store(Request $request)
{
    // 订单验证与创建逻辑
    $order = Order::create($request->validated());

    // 广播订单创建事件
    broadcast(new OrderCreated($order));

    return response()->json($order, 201);
}

三、Next.js前端实现

1. 管理员前端(接收实时订单推送)

创建订单监听组件components/AdminOrderListener.js:

import { useEffect } from 'react';
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';

// 客户端初始化Echo(仅在浏览器环境执行)
if (typeof window !== 'undefined') {
    window.Pusher = Pusher;
    window.Echo = new Echo({
        broadcaster: 'pusher',
        key: process.env.NEXT_PUBLIC_PUSHER_APP_KEY,
        cluster: process.env.NEXT_PUBLIC_PUSHER_APP_CLUSTER,
        wsHost: process.env.NEXT_PUBLIC_PUSHER_HOST,
        wsPort: process.env.NEXT_PUBLIC_PUSHER_PORT,
        forceTLS: false,
        encrypted: false,
        disableStats: true,
    });
}

export default function AdminOrderListener({ onNewOrder }) {
    useEffect(() => {
        // 订阅管理员频道,监听订单创建事件
        const channel = window.Echo.channel('admin.orders');
        channel.listen('.order.created', (event) => {
            // 将新订单传递给父组件更新列表
            onNewOrder(event.order);
        });

        // 组件卸载时取消监听
        return () => {
            channel.stopListening('.order.created');
        };
    }, [onNewOrder]);

    return null;
}

在管理员订单列表页面pages/admin/orders.js中使用:

import { useState, useEffect } from 'react';
import AdminOrderListener from '../../components/AdminOrderListener';

export default function AdminOrders() {
    const [orders, setOrders] = useState([]);

    // 初始化加载已有订单
    useEffect(() => {
        fetch('/api/admin/orders')
            .then(res => res.json())
            .then(data => setOrders(data));
    }, []);

    // 处理新订单,添加到列表头部
    const handleNewOrder = (newOrder) => {
        setOrders(prev => [newOrder, ...prev]);
    };

    return (
        <div className="admin-orders">
            <h1>实时订单列表</h1>
            <AdminOrderListener onNewOrder={handleNewOrder} />
            <ul>
                {orders.map(order => (
                    <li key={order.id}>
                        订单号:{order.sn} | 客户:{order.customer_name} | 状态:{order.status}
                    </li>
                ))}
            </ul>
        </div>
    );
}

2. 客户前端(提交订单)

客户前端只需调用Laravel的REST API提交订单,无需额外WebSocket逻辑,订单创建后Laravel会自动广播事件:

// pages/customer/book.js
import { useState } from 'react';

export default function CustomerBooking() {
    const [formData, setFormData] = useState({
        customer_name: '',
        service_type: '',
        booking_time: ''
    });

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            const res = await fetch('/api/orders', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${localStorage.getItem('user_token')}`
                },
                body: JSON.stringify(formData)
            });
            if (res.ok) {
                alert('预订成功!');
                setFormData({ customer_name: '', service_type: '', booking_time: '' });
            }
        } catch (err) {
            console.error('提交失败', err);
        }
    };

    return (
        <form onSubmit={handleSubmit} className="booking-form">
            <div>
                <label>姓名:</label>
                <input
                    type="text"
                    value={formData.customer_name}
                    onChange={(e) => setFormData({...formData, customer_name: e.target.value})}
                    required
                />
            </div>
            <div>
                <label>服务类型:</label>
                <input
                    type="text"
                    value={formData.service_type}
                    onChange={(e) => setFormData({...formData, service_type: e.target.value})}
                    required
                />
            </div>
            <div>
                <label>预订时间:</label>
                <input
                    type="datetime-local"
                    value={formData.booking_time}
                    onChange={(e) => setFormData({...formData, booking_time: e.target.value})}
                    required
                />
            </div>
            <button type="submit">提交预订</button>
        </form>
    );
}

四、自建WebSocket服务器(替代第三方Pusher)

如果不想依赖Pusher服务,可以用laravel/websockets搭建自己的WebSocket服务器:

# 安装包
composer require beyondcode/laravel-websockets
# 发布迁移文件并执行迁移
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
# 启动WebSocket服务器
php artisan websockets:serve

启动后,.env中的PUSHER_HOST设为localhost,端口6001即可,前端代码无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 12:53:16