返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >TP5与基于workerman的GatewayWorker框架实战在线客服教程【即时通讯】
  • 396
分享到

TP5与基于workerman的GatewayWorker框架实战在线客服教程【即时通讯】

javascript前端php 2023-09-14 16:09:28 396人浏览 八月长安
摘要

一、前期准备 环境搭建 GatewayWorker手册页面直接下载demo(根据自己使用的环境下载) 觉得我的不标准的话可以去哔哩哔哩上看看《码农技术社区》这位大佬的视频挺详细的我就是跟着视频学会的

一、前期准备 环境搭建

GatewayWorker手册页面直接下载demo(根据自己使用的环境下载)在这里插入图片描述
觉得我的不标准的话可以去哔哩哔哩上看看《码农技术社区》这位大佬的视频挺详细的我就是跟着视频学会的

下载出来是长这个样子的

在这里插入图片描述

运行的话直接双击start_for_win.bat就可以了,停止的话ctrl+c,再打y回车就可以了,如图:

启动的样子
在这里插入图片描述
停止的样子

在这里插入图片描述

首先把GatewayWorker复制到tp5的vendor里面,如图:

在这里插入图片描述
打开vendor/GatewayWorker/Applications/YourApp/start_gateway.PHP,把tcp协议改成websocket

在这里插入图片描述
在这里插入图片描述

二、长连接实现群发,初次体验

然后随便找个模板,随便发个消息试试,如图:

在这里插入图片描述

实例代码:

var ws = new WEBSocket("ws://127.0.0.1:8282");ws.onmessage = function(e){    console.log(e)}$(".send-btn").click(function(){    var content = $(".send-input").val();    ws.send(content)    $(".send-input").val("");})

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、群发及客户端和socket服务器保持长连接双向消息推送

然后再稍微改动一下就可以得到一个有点小问题的聊天(也不能说问题因为是向所有人发送信息所以回自己哪里也会多一条信息)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码改动部分(改完Events.php一定要重启start_for_win.bat,否则不生效)

在这里插入图片描述

public static function onMessage($client_id, $message){    $message_data = JSON_decode($message,true);    if(!$message_data){       return;    }    switch($message_data['type']){        case 'say';        $data = [            'type' => 'text',            'id' => $client_id,            'data' => $message_data['data'],        ];        Gateway::sendToAll(json_encode($data));        return;    }    // 向所有人发送     // Gateway::sendToAll("$client_id said $message\r\n");}

页面js部分

在这里插入图片描述

var ws = new WebSocket("ws://127.0.0.1:8282");ws.onmessage = function(e){    // eval() 函数计算 javascript 字符串,并把它作为脚本代码来执行。    // console.log(e)    var msg = eval("("+e.data+")");    // console.log(msg)    switch(msg.type){        case 'text':        var html = '
' +'' +''+msg.data+'' +'
'
$(".chat-content").append(html); return; }}$(".send-btn").click(function(){ var content = $(".send-input").val(); // var res = '{"data":"'+content+'","type":"say"}'; var res = { 'data':content, 'type':'say', }; //JSON.stringify json转字符串 ws.send(JSON.stringify(res)) var html = '
' +''+content+'' +'' +'
'
; $(".chat-content").append(html); $(".send-input").val("");})

四、长连接绑定客户id实现一对一聊天

消息通过用户id来发送信息,效果如图:

这里1给2发送了一个你好啊,2给1发了个我很好

在这里插入图片描述在这里插入图片描述

而3哪里啥都没有

在这里插入图片描述

首先呢获取你的id跟对方的id发给页面

在这里插入图片描述

public function index(){    $input = input('get.');                    //fromid个人id   toid 对方id    $this->assign(['fromid'=>$input['fromid'],'toid'=>$input['toid']]);    return $this->fetch();}

并在前台接受并传给终端告诉他我是谁又要发给谁

在这里插入图片描述

var fromid = {$fromid};//个人idvar toid = {$toid};//他人id// console.log(fromid)// console.log(toid)var ws = new WebSocket("ws://127.0.0.1:8282");ws.onmessage = function(e){    // eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。    // console.log(e)    var msg = eval("("+e.data+")");    // console.log(msg)    switch(msg.type){        case 'init':            var bind = {                'type':'bind',                'fromid':fromid,            };            //JSON.stringify  json转字符串            ws.send(JSON.stringify(bind))        return        case 'text':            //判断是否是当前聊天对象 是的话才会展示                if(toid == msg.toid){                    var html = '
' +'' +''+msg.data+'' +'
'
$(".chat-content").append(html); } return; }}$(".send-btn").click(function(){ var content = $(".send-input").val(); // var res = '{"data":"'+content+'","type":"say"}'; var res = { 'data':content, 'type':'say', 'fromid':fromid, 'toid':toid, }; //JSON.stringify json转字符串 ws.send(JSON.stringify(res)) var html = '
' +''+content+'' +'' +'
'
; $(".chat-content").append(html); $(".send-input").val("");})

然后Events.php里面进行获取并绑定,还有发送信息绑定对方id,其他根据自己要求来 (改完Events.php一定要重启start_for_win.bat,否则不生效)

在这里插入图片描述

public static function onConnect($client_id)    {        // 向当前client_id发送数据         // Gateway::sendToClient($client_id, "Hello $client_id\r\n");        // 向所有人发送        // Gateway::sendToAll("$client_id login\r\n");                //向客户端client_id发送$send_data数据。如果client_id对应的客户端不存在或者不在线则自动丢弃发送数据        Gateway::sendToClient($client_id,json_encode([            'type'=>'init',            'client_id'=>$client_id,        ]));    }           public static function onMessage($client_id, $message)    {        $message_data = json_decode($message,true);        if(!$message_data){           return;        }        switch($message_data['type']){            case 'bind':                //为啥这个绑定不在一开始连接时触发的时候绑定,因为是一开始才会触发的绑定,给别人发的话还得刷新才行,所以就在发消息的时候绑定id                //将client_id与uid绑定,以便通过Gateway::sendToUid($uid)发送数据,通过Gateway::isUidOnline($uid)用户是否在线。                //uid解释:这里uid泛指用户id或者设备id,用来唯一确定一个客户端用户或者设备。                Gateway::bindUid($client_id,$message_data['fromid']);            return;            case 'say';                $data = [                    'type' => 'text',                    'data' => $message_data['data'],                    'fromid'=>$message_data['fromid'],                    'toid'=>$message_data['toid'],                    'time'=>time(),                ];                // 向uid绑定的所有在线client_id发送数据。                // 注意:默认uid与client_id是一对多的关系,如果当前uid下绑定了多个client_id,则多个client_id对应的客户端都会收到消息,这类似于PC QQ和手机QQ同时在线接收消息。                Gateway::sendToUid($message_data['toid'],json_encode($data));                // 向所有人发送                 // Gateway::sendToAll(json_encode($data));            return;        }        // 向所有人发送         // Gateway::sendToAll("$client_id said $message\r\n");    }

五、getwayworker长连接下的普通文本消息之聊天记录持久化

在这里插入图片描述
前台代码:

doctype html><html><head>    <meta charset="utf-8">    <meta name="fORMat-detection" content="telephone=no" />    <title>沟通中title>    <link rel="stylesheet" type="text/CSS" href="__STATIC__/Gatewayworker/css/themes.css?v=2017129">    <link rel="stylesheet" type="text/css" href="__STATIC__/Gatewayworker/css/h5app.css">    <link rel="stylesheet" type="text/css" href="__STATIC__/Gatewayworker/fonts/iconfont.css?v=2016070717">    <script src="__STATIC__/Gatewayworker/js/Jquery.min.js">script>    <script src="__STATIC__/Gatewayworker/js/dist/flexible/flexible_css.debug.js">script>    <script src="__STATIC__/Gatewayworker/js/dist/flexible/flexible.debug.js">script>head><body ontouchstart><div class='fui-page-group'><div class='fui-page chatDetail-page'>    <div class="chat-header flex">        <i class="icon icon-toleft t-48">i>        <span class="shop-titlte t-30">{$to.name}span>        <span class="shop-online t-26">span>        <span class="into-shop">进店span>    div>    <div class="fui-content navbar" style="padding:1.2rem 0 1.35rem 0;">        <div class="chat-content">            <p style="display: none;text-align: center;padding-top: 0.5rem" id="more"><a>加载更多a>p>            {foreach $chat_record as $k => $v}    <p class="chat-time"><span class="time">{$v.add_time}span>p>                {if $from.id == $v.fromid}                <div class="chat-text section-left flex">                                        <span class="char-img" style="background-image: url({$to.toux})">span>                    <span class="text"><i class="icon icon-sanjiao4 t-32">i>{$v.content}span>                div>                {else}                <div class="chat-text section-right flex">                    <span class="text"><i class="icon icon-sanjiao3 t-32">i>{$v.content}span>                                        <span class="char-img" style="background-image: url({$from.toux})">span>                div>                {/if}            {/foreach}        div>    div>    <div class="fix-send flex footer-bar">        <i class="icon icon-emoji1 t-50">i>        <input class="send-input t-28" maxlength="200">        <i class="icon icon-add t-50" style="color: #888;">i>        <span class="send-btn">发送span>    div>div>div><script>    var fromid = {$from.id};//发送者id    var toid = {$to.id};//接收者id    // console.log(fromid)    // console.log(toid)    //连接服务器    var ws = new WebSocket("ws://127.0.0.1:8282");    //调用的方法均在GatewayWorker/Applications/Events.php里面的生命周期函数里面规定    //作用与Worker::$onMessage回调相同,区别是只针对当前连接有效,也就是可以针对某个连接的设置onMessage回调。    ws.onmessage = function(e){        // eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行。        // console.log(e)        //获取他人发送来的信息        var msg = eval("("+e.data+")");        switch(msg.type){            case 'init':                //绑定id                var bind = {                    'type':'bind',                    'fromid':fromid,                };                //JSON.stringify  json转字符串  send执行异步连接操作。此方法会立刻返回。 向客户端发送数据                ws.send(JSON.stringify(bind))                //判断是否在线 发过去  //初次加载判断是否在线                var online = {                    'type':'online',                    'toid':toid,                    'fromid':fromid,                };                ws.send(JSON.stringify(online))                //聊天内容定位到最下面                $('.chat-content').scrollTop(3000);            return            //接受消息            case 'text':                //用当前他人id跟他人发送过的fromid来对比   判断是否是当前聊天对象 是的话才会展示                if(toid == msg.fromid){                    var html = '
' // +'' +'' +''+msg.data+'' +'
'
$(".chat-content").append(html); //聊天内容定位到最下面 $('.chat-content').scrollTop(3000); } return; //保存消息 从而消息持久化 case 'save': //发送消息更新在线状态 if(msg.isread == 2){ $('.shop-online').text('在线'); }else{ $('.shop-online').text('不在线'); } save_message(msg);//调用 保存聊天数据 方法 //聊天内容定位到最下面 $('.chat-content').scrollTop(3000); return; //判断是否在线 回调 case 'online': //初次加载判断是否在线 if(msg.status == 1){ $('.shop-online').text('在线'); }else{ $('.shop-online').text('不在线'); } return; } } //发送信息 $(".send-btn").click(function(){ var content = $(".send-input").val(); // var res = '{"data":"'+content+'","type":"say"}'; var res = { 'data':content, 'type':'say', 'fromid':fromid, 'toid':toid, }; //聊天内容定位到最下面 $('.chat-content').scrollTop(3000); //JSON.stringify json转字符串 ws.send(JSON.stringify(res)) var html = '
' +''+content+'' // +'' +'' +'
'
; $(".chat-content").append(html); $(".send-input").val(""); }) //保存聊天数据 function save_message(data){ $.ajax({ type: "POST", url: "{:url('Gatewayworker/save_message')}", dataType: "json", data:{data}, success: function(res) {} }) }
script>body>html>

后台代码:

namespace app\index\controller;use think\Db;use think\Controller;class Gatewayworker extends Controller{    //聊天页面    public function index(){        $input = input('get.');        //fromid 发送者id   toid 接收者id        $from = db('admin')->where('id',$input['fromid'])->field('id,name,toux')->find();        $to = db('admin')->where('id',$input['toid'])->field('id,name,toux')->find();        //聊天记录   (不完美,除了二者的聊天记录别人的只要满足条件的也会显示出来)        $chat_record = db('chat_record')        ->where(['fromid'=>$input['fromid'],'toid'=>$input['toid']])        ->whereOr(['fromid'=>$input['toid'],'toid'=>$input['fromid']])        ->page(1,10)        ->order('chat_record_id')        ->select();        // halt($chat_record);        foreach($chat_record as $k => $v){            $chat_record[$k]['add_time'] = date('Y-m-d H:i:s',$v['add_time']);        }        $this->assign(['from'=>$from,'to'=>$to,'chat_record'=>$chat_record]);        return $this->fetch();    }    //保存聊天数据    public function save_message(){        $input = input('post.data');        $data=[            'fromid'=>$input['fromid'],            'fromname'=>$this->getname($input['fromid']),//获取发送者name            'toid'=>$input['toid'],            'toname'=>$this->getname($input['toid']),//获取接收者name            'content'=>$input['data'],            'add_time'=>$input['time'],            'isread'=>$input['isread'],//消息是否在线(1在线 2下线)            'type'=>1,//消息类型(1文本消息 2图片 )        ];        db('chat_record')->insert($data);    }    //获取发送者或接收者name    public function getname($id){        $data = db('admin')->where('id',$id)->field('id,name')->find();        return $data['name'];    }    }

Events.php里面的代码:

//declare(ticks=1);use \GatewayWorker\Lib\Gateway;/修改了这个文件一定要重启,否则不起作用class Events{        public static function onConnect($client_id)    {        // 向当前client_id发送数据         // Gateway::sendToClient($client_id, "Hello $client_id\r\n");        // 向所有人发送        // Gateway::sendToAll("$client_id login\r\n");                //向客户端client_id发送$send_data数据。如果client_id对应的客户端不存在或者不在线则自动丢弃发送数据        Gateway::sendToClient($client_id,json_encode([            'type'=>'init',            'client_id'=>$client_id,        ]));    }           public static function onMessage($client_id, $message)    {        //把前台发送过来的字符串转成数组        $message_data = json_decode($message,true);        if(!$message_data){           return;        }        switch($message_data['type']){            //绑定id            case 'bind':                //为啥这个绑定不在一开始连接时触发的时候绑定,因为是一开始才会触发的绑定,给别人发的话还得刷新才行,所以就在发消息的时候绑定id                //将client_id与uid绑定,以便通过Gateway::sendToUid($uid)发送数据,通过Gateway::isUidOnline($uid)用户是否在线。                //uid解释:这里uid泛指用户id或者设备id,用来唯一确定一个客户端用户或者设备。                Gateway::bindUid($client_id,$message_data['fromid']);            return;            case 'online':                //初次加载 判断接收者是否在线                $status = Gateway::isUidOnline($message_data['toid']);                $data=[                    'type'=>'online',                    'status'=>$status,                ];                // 向uid绑定的所有在线client_id发送数据。                // 注意:默认uid与client_id是一对多的关系,如果当前uid下绑定了多个client_id,则多个client_id对应的客户端都会收到消息,这类似于PC QQ和手机QQ同时在线接收消息。                //给发送者发送过去告诉他接收者是否在线                Gateway::sendToUid($message_data['fromid'],json_encode($data));return;            //发送消息   数据保存            case 'say';                $data = [                    'type' => 'text',//文本类型                    'data' => $message_data['data'],//发送内容                    'fromid'=>$message_data['fromid'],//发送者id                    'toid'=>$message_data['toid'],//接收者id                    'time'=>time(),//当前时间                ];                //判断接收者是否在线  //发送消息更新在线状态                if(Gateway::isUidOnline($message_data['toid'])){                    $data['isread'] = 2;//在线                    // 向uid绑定的所有在线client_id发送数据。                    // 注意:默认uid与client_id是一对多的关系,如果当前uid下绑定了多个client_id,则多个client_id对应的客户端都会收到消息,这类似于PC QQ和手机QQ同时在线接收消息。                    Gateway::sendToUid($message_data['toid'],json_encode($data));                }else{                    $data['isread'] = 1;//不在线                }                //类型设置为保存                $data['type']='save';                //告诉发送者 保存聊天数据 从来保证数据持久化 (workerman官方建议这里只写发送消息逻辑,所以保存到数据库交给前台ajax来)                Gateway::sendToUid($message_data['fromid'],json_encode($data));                // 向uid绑定的所有在线client_id发送数据。                // 注意:默认uid与client_id是一对多的关系,如果当前uid下绑定了多个client_id,则多个client_id对应的客户端都会收到消息,这类似于PC QQ和手机QQ同时在线接收消息。                // Gateway::sendToUid($message_data['toid'],json_encode($data));                // 向所有人发送                 // Gateway::sendToAll(json_encode($data));            return;        }        // 向所有人发送         // Gateway::sendToAll("$client_id said $message\r\n");    }          public static function onClose($client_id)    {       // 向所有人发送     //    GateWay::sendToAll("$client_id loGout\r\n");    }}

来源地址:https://blog.csdn.net/qq_44678350/article/details/125521558

--结束END--

本文标题: TP5与基于workerman的GatewayWorker框架实战在线客服教程【即时通讯】

本文链接: https://lsjlt.com/news/407507.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作