SWOOLE開發(fā)實時聊天系統(tǒng)(八)觀察者模式的調(diào)用

首先,新建一個注冊類,在這個類中,寫用戶注冊的具體實現(xiàn)。

<?php
namespace app\services;
use pool\pool;
class LoginService extends CommonService
{
    public function __construct($server) {
        $this->server = $server;
        parent::__construct();
    }
    public function register($frame, $params) {
        try {
            //注冊 一級和二級topic不能為空。
            if (!$params['first_topic'] || !$params['second_topic']) {
                throw new \Exception("當前用戶的分組不存在,請重試!");
            }
            if (!$params['user_id']) {
                throw new \Exception("用戶ID不存在,請重試!");
            }
            $result=$this->saveToRedis($frame,$params);
            //TODO 插入redis出錯處理
            if(!$result){
                throw new \Exception('插入redis出錯,請重試!');
            }
            $this->notify();
        } catch (\Exception $e) {
            $this->result['status'] = 1;
            $this->result['msg'] = $e->getMessage();
            echo json_encode($this->result,JSON_UNESCAPED_UNICODE);
        }
        return $this->result;
    }
    /**
     * 用戶斷開后的操作
     * @param $fd int ws的fd標識
     */
    public static function close($fd) {
    }
    private function saveToRedis($frame,$params){
        //存入組-用戶中
        $rk = str_replace(['first_topic', 'second_topic'], [$params['first_topic'], $params['second_topic']], self::redis_key_group_user);
        $user_list = [];
        if (pool::redis()->exists($rk)) {
            $user_list = explode(",", pool::redis()->get($rk));
        }
        $user_list[] = $params['user_id'];
        pool::redis()->set($rk, implode(",", array_unique(array_filter($user_list))));

        //存入 用戶-組
        $rk = str_replace('fd', $frame->fd, self::redis_key_user_group);
        pool::redis()->set($rk, $params['first_topic'] . "_" . $params['second_topic']);
        //用戶對應(yīng)的fd
        pool::redis()->hSet(self::user_bind_redis_key, $frame->fd, $params['user_id']);
        //fd對應(yīng)的user
        pool::redis()->hSet(self::fd_bind_user_redis_key, $params['user_id'], $frame->fd);
        return true;
    }
}

在這個類中,并沒有寫通知的具體內(nèi)容,只是首先需要繼承一下CommonService,在CommonService中繼承了PushEventGenerator這個類,所以在LoginService中可以直接調(diào)用PushEventGenerator的notify方法。
這樣做的好處是,只要有了通知,在調(diào)用notify方法之后,就會自動一條條去調(diào)用通知,而無需在業(yè)務(wù)代碼中寫通知的具體實現(xiàn)。

<?php
namespace app\services;
use app\services\push\PushEventGenerator;
use pool\pool;
use services\LogService;
/**
 * Class CommonService
 * @package app\services
 */
class CommonService extends PushEventGenerator
{
    const  redis_key_group_user = 'ws_topic_first_topic_second_topic';//分組下對應(yīng)的用戶
    const  redis_key_user_group = 'ws_user_fd';//用戶對應(yīng)的分組
    const  user_bind_redis_key = "ws_user_bind_fd_redis_key";//fd綁定用戶的redis_key fd=》user
    const  fd_bind_user_redis_key = "ws_fd_bind_user_redis_key";//用戶綁定fd的redis_key user=>fd
    const  redis_expire_time=86400;
    public  $result = ['status' => 0, 'msg' => 'success', 'data' => []];
    public  $server;
    public function __construct() {
    }
}

最后,我們回到MessageController中,在getMessage中,判斷用戶發(fā)送信息的類型。

    public function getMessage(\swoole_websocket_frame $frame)
    {
        $data=json_decode($frame->data,true);
        switch($data['type']){
            case 'login':
                $loginService = new LoginService($this->server);
                //注入推送給自己注冊成功的方法;
                $pushtoselfstatus = new PushToSelfRegisterInfo($this->server, '注冊成功', [$frame->fd]);
                $loginService->addPushObServer($pushtoselfstatus);
                //注入推送給所有人 “xxx進入房間”的消息。
                //拼裝消息體
                $msgService=new MessageService();
                $data=$msgService->getMessageContent($data,0);
                $userService = new UserService();
                $fds = $userService->getFdByGroup($data['first_topic'], $data['second_topic']);
                $pushToAll = new PushToAllMessage($this->server,$data,$fds);
                $loginService->addPushObServer($pushToAll);
                $result = $loginService->register($frame, $data);
                if($result['status']!=0){
                    echo json_encode($result,JSON_UNESCAPED_UNICODE) ."\n";
                }
                break;
        }
    }

如果type是‘login’,那么就可以直接調(diào)用LoginService中的方法。
在調(diào)用之前,注入PushToSelfRegisterInfo和PushToAllMessage的類,這樣在登錄完成之后,就可以直接完成推送通知的需求了。

我們打開兩個測試工具,分別輸入10086和10087這兩個用戶,可以看到,如下的結(jié)果

結(jié)果如圖所示:


10086.png
10087.png

OK,下一步我們就可以進行收發(fā)消息的開發(fā)了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容