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:onHandShakeListener:handle加一行代码echo spl_object_id($websocket), PHP_EOL;,看看是否一致。

生命周期级的容器

早于runInSandbox的实例会存在于应用的整个生命周期,比如think\swoole\websocket\Room,基于此可以实现http下向websocket推送消息。

  1. 每个会话都加入同一个房间

    <?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');
     }
    }
  2. 在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 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!