think-swoole的容器、依赖注入与门面
会话级的容器
在业务代码层面,think-swoole基于sandbox
实现了会话级的容器,也就是每个会话都有一个独立的容器,以此实现了跟fpm下代码的最大化兼容。
下面以websocket举个例子(每个加群的人都会问):
<?php
declare (strict_types = 1);
namespace app\listener;
use app\facade\Websocket as AppWebsocket;
use think\swoole\Websocket;
class WebsocketOpen
{
public function __construct(private Websocket $websocket)
{
}
public function handle($event)
{
echo 'this: ' . $this->websocket->getSender(), PHP_EOL;
echo 'app: ' . app(Websocket::class)->getSender(), PHP_EOL;
echo 'facade: ' . AppWebsocket::getSender(), PHP_EOL;
assert($this->websocket === app(Websocket::class));
}
}
这个监听器示范了三种获取websocket fd
的办法,分别是依赖注入、容器和门面,是不是看着跟fpm下一样的用法? 没看错,就是一样的。
总有人问怎么拿fd
,然后可能会去改Handler
代码,比如把$this->event->trigger('swoole.websocket.Close');
改成$this->event->trigger('swoole.websocket.Close', $this->websocket);
,其实是不需要的,你可以在任意位置从容器里拿到Websocket
对象。
不必担心拿到别的连接,拿出来的就是你要的。
不放心的话分别去InteractsWithWebsocket:onHandShake
和Listener:handle
加一行代码echo spl_object_id($websocket), PHP_EOL;
,看看是否一致。
生命周期级的容器
早于runInSandbox
的实例会存在于应用的整个生命周期,比如think\swoole\websocket\Room
,基于此可以实现http下向websocket推送消息。
每个会话都加入同一个房间
<?php declare (strict_types = 1); namespace app\listener; use think\swoole\Websocket; class WebsocketOpen { public function __construct(private Websocket $websocket) { } public function handle($event) { $this->websocket->join('global'); } }
在http下获取所有客户端以及向指定客户端推消息
<?php namespace app\controller; use app\BaseController; use think\swoole\websocket\Room; use think\swoole\websocket\Pusher; class Index extends BaseController { public function index(Pusher $pusher, string $id, string $msg) { $pusher->to($id)->emit('test', $msg); return 'ok'; } public function hello(Room $room, $name = 'global') { return json($room->getClients($name)); } }
访问
http://localhost:9501/hello/global
可获取所有房间(客户端fd)
访问http://localhost:9501/?id=ID&msg=MESSAGE
可向指定客户端推送消息。
本作品采用《CC 协议》,转载必须注明作者和本文链接