clue / reactphp-eventsource
即时实时更新。轻量级EventSource客户端通过HTML5服务器端发送事件(SSE)接收实时消息。基于ReactPHP事件驱动架构的快速流处理。
Requires
- php: >=5.4
- evenement/evenement: ^3.0 || ^2.0
- react/event-loop: ^1.2
- react/http: ^1.6
- react/promise: ^3 || ^2.10 || ^1.2.1
Requires (Dev)
- phpunit/phpunit: ^9.6 || ^5.7 || ^4.8.36
README
即时实时更新。轻量级EventSource客户端通过HTML5服务器端发送事件(SSE)接收实时消息。基于ReactPHP事件驱动架构的快速流处理。
目录
支持我们
我们在开发、维护和更新我们出色的开源项目上投入了大量时间。您可以通过成为GitHub的赞助商来帮助我们保持这种高质量的工作。赞助商将获得许多回报,有关详细信息,请参阅我们的赞助页面。
让我们一起将这些项目提升到新的水平!🚀
快速入门示例
安装后,您可以使用以下代码从任何服务器端发送事件(SSE)服务器端点流消息
data: {"name":"Alice","message":"Hello everybody!"}
data: {"name":"Bob","message":"Hey Alice!"}
data: {"name":"Carol","message":"Nice to see you Alice!"}
data: {"name":"Alice","message":"What a lovely chat!"}
data: {"name":"Bob","message":"All powered by ReactPHP, such an awesome piece of technology :)"}
$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php'); $es->on('message', function (Clue\React\EventSource\MessageEvent $message) { $json = json_decode($message->data); echo $json->name . ': ' . $json->message . PHP_EOL; });
查看示例。
用法
EventSource
EventSource
类负责与远程服务器端发送事件(SSE)端点进行通信。
EventSource
对象与常见网络浏览器中找到的对象非常相似。除非另有说明,否则它遵循https://html.whatwg.com.cn/multipage/server-sent-events.html下定义的相同语义。
其构造函数只需提供远程服务器端发送事件(SSE)端点的URL即可。
$es = new Clue\React\EventSource\EventSource('https://example.com/stream.php');
如果您需要自定义连接器设置(DNS解析、TLS参数、超时、代理服务器等),您可以将自定义的ConnectorInterface
实例显式传递给Browser
实例,并将其作为附加参数传递给EventSource
,如下所示
$connector = new React\Socket\Connector([ 'dns' => '127.0.0.1', 'tcp' => [ 'bindto' => '192.168.10.1:0' ], 'tls' => [ 'verify_peer' => false, 'verify_peer_name' => false ] ]); $browser = new React\Http\Browser($connector); $es = new Clue\React\EventSource\EventSource('https://example.com/stream.php', $browser);
此类接受一个可选的LoopInterface|null $loop
参数,可以用来传递用于此对象的事件循环实例。您可以使用null
值来使用默认循环。除非您确定您想显式使用给定的事件循环实例,否则不应提供此值。
消息事件
每当接收到EventSource消息时,将发出message
事件。
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) { // $json = json_decode($message->data); var_dump($message); });
EventSource流在其生命周期内可能发出任意数量的消息。每个message
事件将接收一个MessageEvent
对象。
可以使用 MessageEvent::$data
属性 来访问消息负载数据。它通常用于传输结构化数据,例如 JSON
data: {"name":"Alice","age":30}
data: {"name":"Bob","age":50}
$es->on('message', function (Clue\React\EventSource\MessageEvent $message) { $json = json_decode($message->data); echo "{$json->name} is {$json->age} years old" . PHP_EOL; });
EventSource 流可以为每个传入的消息指定一个事件类型。可以使用此 event
字段来触发适当的事件类型,如下所示
data: Alice
event: join
data: Hello!
event: chat
data: Bob
event: leave
$es->on('join', function (Clue\React\EventSource\MessageEvent $message) { echo $message->data . ' joined' . PHP_EOL; }); $es->on('chat', function (Clue\React\EventSource\MessageEvent $message) { echo 'Message: ' . $message->data . PHP_EOL; }); $es->on('leave', function (Clue\React\EventSource\MessageEvent $message) { echo $message->data . ' left' . PHP_EOL; });
有关更多详细信息,请参阅 MessageEvent::$type
属性。
打开事件
当 EventSource 连接成功建立时,将触发 open
事件。
$es->on('open', function () { echo 'Connection opened' . PHP_EOL; });
一旦 EventSource 连接打开,它可以触发任意数量的 message
事件。
如果无法成功打开连接,将触发一个 error
事件。
错误事件
当 EventSource 连接失败时,将触发 error
事件。事件接收一个 Exception
参数作为错误实例。
$redis->on('error', function (Exception $e) { echo 'Error: ' . $e->getMessage() . PHP_EOL; });
当 EventSource 连接临时断开时,将自动重试连接。如果服务器发送非成功的 HTTP 状态码或无效的 Content-Type
响应头,连接将永久失败。
$es->on('error', function (Exception $e) use ($es) { if ($es->readyState === Clue\React\EventSource\EventSource::CLOSED) { echo 'Permanent error: ' . $e->getMessage() . PHP_EOL; } else { echo 'Temporary error: ' . $e->getMessage() . PHP_EOL; } });
请参阅 EventSource::$readyState
属性。
EventSource::$readyState
可以使用 int $readyState
属性来检查当前的 EventSource 连接状态。
该状态是只读的,在其生命周期内可以处于三种状态之一
EventSource::CONNECTING
EventSource::OPEN
EventSource::CLOSED
EventSource::$url
可以使用 readonly string $url
属性来获取构造函数中给出的 EventSource URL。
close()
可以使用 close(): void
方法强制关闭 EventSource 连接。
这将关闭任何活动的连接或连接尝试,并进入 EventSource::CLOSED
状态。
MessageEvent
MessageEvent
类表示一个传入的 EventSource 消息。
MessageEvent::__construct()
可以使用 new MessageEvent(string $data, string $lastEventId = '', string $type = 'message')
构造函数来创建一个新的 MessageEvent
实例。
这通常用于内部表示每个传入的消息事件(另请参阅 message
事件)。同样,您也可以在测试用例中使用此类来测试应用程序对传入消息的反应。
构造函数验证并初始化此类中所有属性。如果任何参数无效,则抛出 InvalidArgumentException
。
MessageEvent::$data
可以使用 readonly string $data
属性来访问消息负载数据。
data: hello
assert($message->data === 'hello');
data
字段可能跨越多行。这通常用于传输结构化数据,例如 JSON
data: {
data: "message": "hello"
data: }
$json = json_decode($message->data); assert($json->message === 'hello');
如果消息不包含 data
字段或 data
字段为空,则消息将被丢弃,不会触发事件。
MessageEvent::$lastEventId
可以使用 readonly string $lastEventId
属性来访问最后一个事件 ID。
data: hello
id: 1
assert($message->data === 'hello'); assert($message->lastEventId === '1');
内部,如果连接中断,将自动将 id
字段用作 Last-Event-ID
HTTP 请求头。
如果消息不包含 id
字段,则 $lastEventId
属性将是最后一个接收到的 ID 的值。如果没有之前的消息包含 ID,则默认为空字符串。
MessageEvent::$type
可以使用 readonly string $type
属性来访问消息事件类型。
data: Alice
event: join
assert($message->data === 'Alice'); assert($message->type === 'join');
内部,将使用 event
字段来触发适当的事件类型。另请参阅 message
事件。
如果消息不包含 event
字段或 event
字段为空,则 $type
属性将默认为 message
。
安装
本项目遵循 SemVer。这将安装最新支持的版本
composer require clue/reactphp-eventsource:^1.2
有关版本升级的详细信息,请参阅变更日志。
本项目旨在在任何平台上运行,因此不要求任何PHP扩展,并支持在旧版PHP 5.4至当前PHP 8+上运行。强烈建议为此项目使用最新支持的PHP版本。
测试
要运行测试套件,首先需要克隆此存储库,然后通过Composer安装所有依赖项
composer install
要运行测试套件,请转到项目根目录并运行
vendor/bin/phpunit
测试套件已配置为始终确保所有支持环境下的100%代码覆盖率。如果您已安装Xdebug扩展,还可以像这样在本地生成代码覆盖率报告
XDEBUG_MODE=coverage vendor/bin/phpunit --coverage-text
许可证
本项目在宽松的MIT许可下发布。
您知道吗?我提供定制开发服务,并发放赞助发行和贡献的发票。请联系我(@clue)以获取详细信息。
更多
-
如果您想了解更多关于处理数据流的信息,请参阅底层react/stream组件的文档。
-
如果您想要运行Server-Sent Events (SSE)应用程序的服务器端,您可能希望使用由Framework X提供的强大服务器实现。