直接用curl向mercure hub的publish端点发post请求即可,无需额外php扩展或sdk;frankenphp自带标准mercure实现,兼容所有http客户端,但需显式启用并正确配置jwt密钥、caddyfile及网络地址。

直接用 curl 向 Mercure Hub 的 Publish 端点发 POST 请求即可,不需要额外 PHP 扩展或 SDK —— FrankenPHP 自带的 Mercure 是标准实现,兼容所有 HTTP 客户端。
确认 Mercure Hub 是否已启用
FrankenPHP 镜像默认不自动启动 Mercure,必须显式启用。检查你的 Caddyfile 或环境变量:
- 若用 Docker 启动,确保传入
-e MERCURE_PUBLISHER_JWT_KEY=...和-e MERCURE_SUBSCRIBER_JWT_KEY=...(两者可相同,但必须非空) - 镜像内置的
Caddyfile中 Mercure 段落默认被注释,需取消注释并补全配置,例如:mercure { publisher_jwt {your_publisher_jwt} {your_key} subscriber_jwt {your_subscriber_jwt} {your_key} transports memory } - 未正确配置时,
curl -v http://localhost/.well-known/mercure会返回 404 或 500,而不是 Mercure 的 discovery JSON
curl_exec 发布消息的最小可行代码
FrankenPHP 的 Mercure Hub 默认监听 http://127.0.0.1:8080/.well-known/mercure(Caddy 内部地址),PHP 进程内直接调用需注意网络可达性:
- 在 Docker 容器中运行 PHP 时,不能用
localhost—— 要用http://host.docker.internal:8080(Mac/Windows)或http://172.17.0.1:8080(Linux),或更稳妥地让 Caddy 反向代理 Mercure 到同一域名下(如/mercure) - JWT 必须由
MERCURE_PUBLISHER_JWT_KEY签发,且 payload 至少含publisher声明;可用openssl快速生成测试 token:echo '{"publisher":"test"}' | openssl dgst -sha256 -hmac "your_key" -binary | openssl enc -base64 - 发布代码示例(无依赖,仅
curl):$url = 'http://host.docker.internal:8080/.well-known/mercure'; $token = 'your_base64_encoded_publisher_jwt'; $data = json_encode(['data' => 'hello', 'type' => 'update']); $headers = [ 'Authorization: Bearer ' . $token, 'Content-Type: application/json', 'Accept: text/event-stream' ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
用 file_get_contents 替代 curl 的坑
部分 FrankenPHP 部署(尤其是静态二进制或某些容器环境)禁用了 allow_url_fopen,此时 file_get_contents('http://...') 会直接失败:
- 检查
ini_get('allow_url_fopen')返回值,为''或'0'即不可用 - 强行开启风险高(尤其生产环境),不推荐;应改用
curl或封装成独立 CLI 命令由exec()调用 - 即使
allow_url_fopen开启,也需确保stream_context_create显式设置http选项中的header和method,否则 JWT 头无法发送
主题(topic)权限与路由匹配
Mercure 默认只允许发布到以 https:// 或 http:// 开头的主题,且必须与 JWT 中 publish 字段声明的前缀匹配:
- JWT 若声明
"publish": ["https://example.com/updates"],则只能发布到https://example.com/updates/*类似路径 - 开发时建议 JWT 设为
"publish": ["*"](仅限本地),对应 token 签发时用{"publish":["*"]} - 发布请求 URL 中的
topic参数必须是完整 URI,例如:http://.../.well-known/mercure?topic=https%3A%2F%2Fexample.com%2Fupdates%2Fuser-123 - 前端
EventSource订阅时 topic 必须完全一致,大小写和编码都要对得上
真正容易卡住的地方不是代码怎么写,而是 JWT 签发密钥、Caddy 内部网络地址、topic 权限三者没对齐 —— 调试时优先用 curl -v 手动测通这三步,再嵌入 PHP。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











