mercure推送必须设id字段,否则eventsource无法维护last-event-id导致重复或跳过更新;三种发布方式均需传字符串id,推荐时间戳+随机字节组合,frankenphp不生成也不校验但依赖其保障事件流语义。

FrankenPHP Mercure 推送必须用 id 字段设事件 ID
Mercure 协议规范要求每个推送事件必须带明确的 id 字段,否则浏览器端 EventSource 无法正确维护事件流位置(last-event-id),会导致重复接收或跳过更新。FrankenPHP 内置的 Mercure Hub 严格遵循该规范,不接受无 id 的事件。
三种发布方式中 id 的写法差异
无论用哪种方式发 Mercure 消息,id 都必须是字符串,且建议为时间戳+唯一标识组合,避免冲突:
- 用
mercure_publish()函数时:mercure_publish('https://example.com/news', ['id' => '20261010183045-abc123', 'data' => '...']) - 用 HTTP POST 到
/.well-known/mercure时:请求体需是application/x-www-form-urlencoded格式,含id=20261010183045-abc123字段 - 用 Symfony Mercure 组件时:在
Update构造中传入new Update($topic, $data, $id),第三个参数即id
不设 id 或设错的典型表现
没加 id 不会报错,但后果隐蔽:
- 浏览器
EventSource每次重连都从头开始拉取,旧事件反复触发 -
event.lastEventId始终为空,无法做断线续推校验 - 多个同主题事件并发推送时,顺序可能错乱(因 Mercure 默认按
id排序) - 使用
retry参数无效——它只对带id的事件生效
生成可靠 id 的实操建议
别用 uniqid()(精度不够、无序),也别用纯时间戳(高并发下易重复):
- 推荐组合:
sprintf('%s-%s', date('YmdHis'), bin2hex(random_bytes(3))) - 若已用 UUID v4,可截取前 12 位作
id(如substr($uuid, 0, 12)),兼顾唯一性与长度 - 避免在
id中嵌入敏感信息(如用户 ID),Mercure 事件可能被中间代理缓存
关键点在于:FrankenPHP 不替你生成 id,也不校验格式,但它依赖这个字段维持事件流语义——漏掉或乱设,前端就收不准。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











