ntavelis/mercure-php
Composer 安装命令:
composer require ntavelis/mercure-php
包简介
Publish messages to mercure hub
README 文档
README
This package publishes notifications to the mercure hub from your php application. These messages can be later consumed from the clients(web-browsers or mobile apps) to provide real-time updates to your application. All of this is possible due to the Mercure protocol, you can read more about the protocol here.
Shoutout to dunglas for his work in the mercure project.
Requirements
- PHP 8.3+
Install
Install the package via Composer
composer require ntavelis/mercure-php
Mercure Hub installation
The mercure hub which is a binary written in GO Lang, should be up and running, in order to accept the messages from the php application.
Please refer to the official documentation on how to Install the hub:
Sending a public notification
We need to publish messages from our php server to the mercure hub and then consume them in our client, in this example in a browser via javascript.
PHP code
The below example is a controller in the Symfony framework:
<?php declare(strict_types=1); namespace App\Controller; use Ntavelis\Mercure\Messages\Notification; use Ntavelis\Mercure\Providers\PublisherTokenProvider; use Ntavelis\Mercure\Publisher; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpClient\Psr18Client; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; class PublishController extends AbstractController { #[Route('/publish', name: 'publish')] public function index(): JsonResponse { $notification = new Notification( topics: ['http://localhost/books/2'], data: ['message' => 'new public event'], ); $publisher = new Publisher( mercureHubUrl: 'http://localhost:3000/.well-known/mercure', tokenProvider: new PublisherTokenProvider('your-very-secret-key-at-least-32-chars'), client: new Psr18Client(), ); $publisher->send($notification); return new JsonResponse(['success']); } }
Note: The publisher requires a PSR-18 compliant HTTP client. This package does not bundle one — you must install and pass it yourself. To use the Symfony HTTP client:
composer require symfony/http-client
Tip: Instead of manually building the classes, you can achieve the same result by using the fluent API.
Notification class
The first argument of the Ntavelis\Mercure\Messages\Notification is an array of topics, you want to publish a notification for. The topics can be any string that makes sense for you, e.g. 'orders', 'clients', 'notes', 'http://localhost/books/2' etc. The second argument is the array of data you want to pass to your client, this array will be json encoded and it will be received from the clients, which can then act upon that received data.
Publisher class
This is the class that it actually sends the notification to the mercure hub, it expects 3 arguments upon instantiation. The mercure hub url, a class that implements the Ntavelis\Mercure\Contracts\TokenProviderInterface (you can use the one from the package or provide your own) and lastly as mentioned above an instance of a PSR-18 compatible client.
Client-side Javascript code
In order to consume the above public message, our client side code will look like this:
// The subscriber subscribes to updates for any topic matching http://localhost/books/{id} const url = new window.URL('http://localhost:3000/.well-known/mercure'); url.searchParams.append('topic', 'http://localhost/books/{id}'); const eventSource = new EventSource(url.toString()); // The callback will be called every time an update is published eventSource.onmessage = e => { console.log(JSON.parse(e.data));// do something with the payload };
Note: We used a wildcard for the id, so we will receive a notification for books with any given {id}.
The above example uses native js code, without any library. Please check the EventSource documentation for more information.
Optionally we can specify a specific type for our topic and listen only for that type in our frontend, more info here
Private messages
Unlike public messages, private messages are not meant to be consumed from everybody. Private messages are messages that are meant to be consumed from authenticated consumers.
To publish and consume private messages we need 3 things:
- To publish a private notification from our php server code.
- Provide an endpoint to generate the JWT token for the clients.
- Make a request from the client to the backend to get the JWT token that proves we are able to receive the private messages and subscribe to events using the token we received.
PHP code (Step 1)
From our PHP server code, we now have to use the Ntavelis\Mercure\Messages\PrivateNotification class, which receives the same arguments as Notification but marks the notification as private.
<?php declare(strict_types=1); namespace App\Controller; use Ntavelis\Mercure\Messages\PrivateNotification; use Ntavelis\Mercure\Providers\PublisherTokenProvider; use Ntavelis\Mercure\Publisher; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpClient\Psr18Client; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Routing\Attribute\Route; class PublishController extends AbstractController { #[Route('/publish', name: 'publish')] public function index(): JsonResponse { $notification = new PrivateNotification( topics: ['http://localhost/author/ntavelis/books/155'], data: ['message' => 'new private event'], ); $publisher = new Publisher( mercureHubUrl: 'http://localhost:3000/.well-known/mercure', tokenProvider: new PublisherTokenProvider('your-very-secret-key-at-least-32-chars'), client: new Psr18Client(), ); $publisher->send($notification); return new JsonResponse(['success']); } }
That's it, we published a private message that is meant only for the user ntavelis as the topic specified http://localhost/author/ntavelis/books/155. Perhaps he is the author of the book in our app and we would like to send a client notification to update his private dashboard.
Tip: Instead of manually building the classes, you can achieve the same result by using the fluent API.
Provide the endpoint that will generate the token for the client (Step 2)
To consume the messages in our javascript, we need to provide a valid token when we subscribe to the hub to prove that we are authorized to receive private notifications. To do this we can make an ajax request to a php endpoint to receive the token. This package will generate the token for us, we only need to provide an endpoint that the client can call to receive the token.
This is the PHP code that generates the token for the client (the subscriber):
<?php declare(strict_types=1); namespace App\Controller; use Ntavelis\Mercure\Providers\SubscriberTokenProvider; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Attribute\Route; class SubscribeController extends AbstractController { #[Route('/subscribe', name: 'subscribe', methods: ['POST'])] public function index(Request $request): JsonResponse { $content = json_decode($request->getContent(), true); $topic = $content['topic']; // TODO: authorize the request before issuing a token $provider = new SubscriberTokenProvider('your-very-secret-key-at-least-32-chars'); $token = $provider->getToken([$topic]); return new JsonResponse(['token' => $token]); } }
In the above example we used the Ntavelis\Mercure\Providers\SubscriberTokenProvider to get the token valid for a particular topic.
Note: To authorize the request is up to you, you should check that the request is valid, and it can receive private notifications for this topic.
Obtain the token in the client and subscribe to events using that token (Step 3)
Final step that puts it all together, from our client-side code we obtain the token, and we subscribe to the events from the hub using this token.
Note: we are going to use a polyfill library in this example to pass the authorization header to the hub, because it is not natively supported from the EventSource.
// use a polyfill library import { EventSourcePolyfill } from 'event-source-polyfill'; // Make a post request to the server to obtain the token for the topic we want to receive notifications for const token = fetch('/subscribe', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({topic: 'http://localhost/author/ntavelis/books/155'}), // send the topic we need to authenticate on }).then(response => response.json()) .then((json) => json.token); // When we have the token subscribe to the EventSource by passing the token token.then((token) => { const url = new window.URL('http://localhost:3000/.well-known/mercure'); url.searchParams.append('topic', 'http://localhost/author/ntavelis/books/155'); // Authorization header const eventSourceInitDict = { headers: { 'Authorization': 'Bearer ' + token } }; const es = new EventSourcePolyfill(url.toString(), eventSourceInitDict); es.onmessage = e => { console.log(JSON.parse(e.data)); }; });
Keep in mind that you can also use cookie based authentication to connect to the hub, you can read more about it here.
Extra
If you want to configure notifications for a specific type, consult the documentation here.
Change log
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING and CODE_OF_CONDUCT for details.
Security
If you discover any security related issues, please email davelis89@gmail.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.
ntavelis/mercure-php 适用场景与选型建议
ntavelis/mercure-php 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 16.85k 次下载、GitHub Stars 达 30, 最近一次更新时间为 2019 年 08 月 26 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「notifications」 「events」 「Broadcast」 「mercure」 「ntavelis」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 ntavelis/mercure-php 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 ntavelis/mercure-php 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 ntavelis/mercure-php 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
A Laravel Nova package that adds a notification feed in your Nova app.
Rabbitevents common package
Push browser notifications in real-time from your TastyIgniter application.
Библиотека для реализаций паттерна Pub/Sub
The Listener component of the RabbitEvents library.
The Publisher component of the RabbitEvents package.
统计信息
- 总下载量: 16.85k
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 30
- 点击次数: 24
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2019-08-26