确认mercure hub已启用且可访问:需检查caddyfile中未注释的mercure块并配置publisher_jwt和subscriber_jwt;docker启动时传入对应环境变量;执行curl -v http://localhost/.well-known/mercure,返回200+json即正常,404或500说明未启用或配置错误。

FrankenPHP 实现实时消息推送,核心就是启用并正确使用它内置的 Mercure Hub —— 不需要额外部署服务、不依赖 WebSocket 库、也不用写长连接管理逻辑。只要配置对、JWT 签得准、URL 主题一致,就能稳定推送。
怎么确认 Mercure Hub 已启用且可访问
FrankenPHP 镜像默认不启动 Mercure,必须显式配置。常见错误是 Caddyfile 里 mercure 块被注释,或环境变量没传全:
- 检查
Caddyfile中是否包含未注释的mercure段,并至少配置publisher_jwt和subscriber_jwt(密钥可相同,但不能为空) - Docker 启动时必须传入
-e MERCURE_PUBLISHER_JWT_KEY=xxx -e MERCURE_SUBSCRIBER_JWT_KEY=xxx - 用
curl -v http://localhost/.well-known/mercure测试:返回 200 + JSON 是正常;404 或 500 说明没启用或配置错
PHP 怎么发布消息(curl 方式最稳)
不要试图用 Guzzle 或自定义 HTTP 客户端封装,FrankenPHP Worker 对连接复用敏感,curl 显式控制更可靠:
- 目标地址不是
localhost:Docker 内 PHP 调用需用http://host.docker.internal:8080/.well-known/mercure(Mac/Windows)或http://172.17.0.1:8080/.well-known/mercure(Linux) - JWT 必须用
MERCURE_PUBLISHER_JWT_KEY签发,payload 至少含{"mercure": {"publish": ["https://example.com/notifications"]}} -
curl_exec()建议设CURLOPT_TIMEOUT_MS = 200,避免阻塞请求 - 主题 URL 必须字节级一致:带尾部斜杠和不带斜杠是两个 topic
前端怎么订阅并稳定接收
浏览器原生 EventSource 是唯一推荐方式,别自己封装 WebSocket 来“模拟” Mercure:
- 订阅 URL 必须带
Authorization: Bearer <subscriber_token></subscriber_token>,token 用MERCURE_SUBSCRIBER_JWT_KEY签发,payload 至少含{"mercure": {"subscribe": ["https://example.com/notifications"]}} - 开发时若用
http://localhost,Caddyfile 里 mercure 块要加insecure指令,否则 401 或连接拒绝 - 不要让前端直接生成 JWT:PHP 后端应提供一个
/api/mercure-token接口返回已签名 token,避免密钥泄露 - EventSource 断连后默认立即重试,容易触发 Caddy 限速(10 次/秒),建议前端加简单退避逻辑
最容易被忽略的是 JWT 密钥的空白符处理:Caddyfile 里写的密钥如果带换行或空格,PHP 侧 base64_decode() 后再传给 openssl_sign() 才能匹配。密钥不一致,前端连得上、收不到;后端发得出去、Hub 拒绝验证——这种问题查日志几乎不报错,只能靠逐字比对。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











