天天看点

thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

此博客参考https://fly.layui.com/jie/12624/

一,程序实现的逻辑:

  1. 后端还是和以前一样,传值给前端。
  2. 前端与GatewayWorker建立连接获取特定的连接id

(这样前端就有用户id和连接id)

    3.前端通过ajax方法发送用户id和链接id给后端,后端进行绑定

    4.监控前端发送消息,发送人id,当触发该事件,传到后端,后端根据用户id值,发送给特定的人

    5.监控前端接收消息,当有新消息过来就在页面执行相应的代码

二,环境的搭建

1,下载GatewayWorker

(地址:http://www.workerman.net/download/GatewayWorker-for-win.zip)

2,修改Applications/YourApp/目录下的start_geteway.php 24行左右 修改为$gateway = new Gateway("websocket://0.0.0.0:8282");(端口号和前端保持一致)

3,下载workerman的GatewayClient(https://github.com/walkor/GatewayClient);

4,将下载好的Gateway重命名为Gateway.class.php并修改命名空间为namespace Org\Util;

thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯
  1. 将前面重命名Gateway.class.php复制到thinkphp/library/org/util/目录下
  2. 双击启动GatewayWorker根目录下的start_for_win.bat()

如果出现下面:

thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

说明启动成功

如果没有启动成功将有以下解决方法

  1. 将php设置为全局环境变量(网上有很多方法)测试是否成功在命令行执行php –v,如果提示“php不是内部或外部命令“之类的就说明没有设置好
  2. 如果有下图之类的提示
thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

上图那样有三个问题

  • php_mcrypt.dll - 找不到指定的模块。
  • php_pdo.dll - 找不到指定的模块。
  • proc_open() has been disabled for security reasons.

找不到指定模块:解决方法打开php.ini文件,查找模块名(比如上图php_pdo.dll);找到在这句前面加上“;”。注释掉即可

has been disabled for security reasons.解决方法:就是把这个方法的禁止打开,也是在php.ini文件修改;找到这个方法,直接删掉即可

三,代码部分

  1. 后端部分
  1. 因为该篇主要讲即时通讯的实现,所以用户信息获取那部逻辑就不做展示。
  2. 后端绑定和发送信息
thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

后端接收前端数据的时候,还做了把数据存入数据库的处理,这样就可以实现数据的持久化

前端部分

  1. 引入文件
<script src="__PUBLIC__/jquery/2.0.0/jquery.js"></script>

<link rel="stylesheet" href="__PUBLIC__/layim/css/layui.mobile.css" target="_blank" rel="external nofollow" >

<script src="__PUBLIC__/layim/layui.js"></script>
           
  1. 自己信息的初始化
layui.use('mobile', function(layim){



    var mobile = layui.mobile

            ,layim = mobile.layim;

    layim.config({

        init: {

            mine: {

                "username": "{$user.name}" //我的昵称

                ,"id": "user{$user.id}" //我的ID

                ,type: 'kh'//类型

                ,"avatar": "{$user.img}" //我的头像

            }

        } , chatTitleColor:"#fff",

        chatLog: '/chat/log/'



    });
           

(3)创建客服信息

layim.chat({

    id: "kf{$kf.id}"

    ,name: '客服{$kf.id}'

    ,type: 'kefu' //friend、group等字符,如果是group,则创建的是群聊

    ,avatar: '/luntan/{$kf.img}'

});
           

(4)建立连接

var socket = new WebSocket('ws://localhost:8282');//服务器改成ip地址加端口号
           

连接方法

第一次连接,会收到两次信息,接收后端传来数据也是在这里处理

thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

我们可以在onmessage方法里面进行处理,取出连接值,再传给后端,这样就绑定好了

除了是登录事件,登出事件,就是后端正常我们自己发送的数据了

我们把接收到的值,再进行展示,这样就可以实现我们需要的效果了。

//连接成功时触发
socket.onopen = function(e){

//这里可以写一些提示语

}

//监听收到的消息
socket.onmessage = function(e){
var data = e.data

// console.log(e);

 data=data.replace('\r\n','');//删除换行符

 var arr=data.split(" ");



 if(arr[0]=="Hello"){



     var client_id=arr[1].trim();



         //绑定client_id

         $.ajax({type: "POST", url: "{:U('Workerman/bind')}", data: {

             'uid':"user{$user['id']}",

             'client_id': client_id}, dataType: 'json', success: function (res) {

             console.log(res);

         }});





 }else if(arr[1]!="login"&&arr[1]!="logout"){

     //接收服务器信息

     data=JSON.parse(data);

     if(data['sendid']=="kf{$kf.id}"){

         $("#link").html("可点击进行评价");

         //console.log(data['sendname']);

         var obj = {};

         obj = {

             username:data['sendname']

             ,avatar:  data['img']

             ,id: 'kf1'

             ,type:"kefu"

             ,content: data['content']

         }

         layim.getMessage(obj);

     }


}
           

(5)监听用户发送信息

layim.on('sendMessage', function(data){

    console.log(data);

    var sendid=data.mine.id;

    var sendtype="kh";

    var sendname=data.mine.username;

    var sendimg=data.mine.avatar;

    var contents=data.mine.content;

    var toid=data.to.id;

    var toname=data.to.name;

    var totype=data.to.type;

    var toimg=data.to.avatar;

    var talkid=data.mine.id+"|"+data.to.id;

    var talktip=data.mine.username+"|"+data.to.name;

    $.ajax({

        type: "POST",

        url: "{:U('User/getcontents')}",

        data: {

            'sendid':sendid,

            'sendname': sendname,

            'sendtype':sendtype,

            'sendimg':sendimg,

            'contents':contents,

            'toid':toid,

            'toname':toname,

            'totype':totype,

            'toimg':toimg,

            'talkid':talkid,

            'talktip':talktip,

        },

        dataType: 'json',

        success: function (res) {

            console.log(res);

        }

    })
           

至此即时通讯的修改就出来

四,数据的持久化,跨设备储存

把聊天记录根据自己的需求存入数据库

单用户进入聊天界面时,根据是谁与谁的聊天,读取相应数据,然后前端得到数据再进行展示。

注意layim聊天记录的要求时间戳是精确到毫秒的

(1),php获取当前毫秒的方法

public function getMillisecond() {

    $time = explode (" ", microtime () );

    $time = $time [1] . ($time [0] * 1000);

    $time2 = explode ( ".", $time );

    $time = $time2 [0];

    return $time;

}
           

(2),前端初始化数据

localStorage.clear();
           

(3),前端获取数据,并展示

$.ajax({type: "POST", url: "{:U('User/getmsg')}", data: {

    'uid':"user{$user['id']}",'kid':"kf{$kf.id}"},

    dataType: 'json', success: function (res) {

        if(res.stu==1){

            $("#link").html("获取历史记录成功");

            var msg=res.msg;

          //  console.log(msg)

            for ($i=0;$i<msg.length;$i++){

                var isme=false;

                if("user{$user['id']}"==msg[$i].sendid){

                    isme=true;

                }



                var obj = {};

                obj = {

                    username:msg[$i].sendname//消息来源用户名

                    ,avatar:  msg[$i].sendimg //消息来源用户头像

                    ,id:  msg[$i].sendid//消息的来源ID(如果是私聊,则是用户id,如果是群聊,则是群组id)

                    ,type:msg[$i].totype //聊天窗口来源类型,从发送消息传递的to里面获取

                    ,content: msg[$i].contents //消息内容

                    ,mine: isme

                    ,timestamp: parseInt(msg[$i].time) //服务端时间戳毫秒数。注意:如果你返回的是标准的 unix 时间戳,记得要 *1000

                }

                layim.getMessage(obj);

            }



        }



    }})
           

这样数据的持久化算是实现了

不过这里还有一个小bug,当执行layim.getMessage()如果是对方数据的时候就有声音提示(也就是上面isme变量为false的时候),所以一打开这个页面就有声音提示,这个是默认打开的,因此我们要把他关闭了

在layim.config里面最后加上“,voice: false“

然后我们自己写收到实时信息的时候发送提示音

Js发送语音提示方法

function playSound() {

    var borswer = window.navigator.userAgent.toLowerCase();

    if ( borswer.indexOf( "ie" ) >= 0 )

    {

        //IE内核浏览器

        var strEmbed = '<embed name="embedPlay" src="/Public/layim/css/modules/layim/voice/default.wav" autostart="true" hidden="true" loop="false"></embed>';

        if ( $( "body" ).find( "embed" ).length <= 0 )

            $( "body" ).append( strEmbed );

        var embed = document.embedPlay;

        embed.volume = 100;

    } else

    {

        //非IE内核浏览器

        var strAudio = "<audio id='audioPlay' src='/Public/layim/css/modules/layim/voice/default.wav' hidden='true'>";

        if ( $( "body" ).find( "audio" ).length <= 0 )

            $( "body" ).append( strAudio );

        var audio = document.getElementById( "audioPlay" );



        //浏览器支持 audion

        audio.play();

    }
           

然后再自己需要提示音的时候调用这个方法即可

效果图

thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯
thinkphp3.2+workerman(GatewayWorker)+ Layim做即时通讯

最后提示:

  1. 如果在服务器搭建的时候记得打开你程序设定的端口的防火墙
  2. 命令行窗口不能关闭
  3. 以上都是在windows系统搭建的 ,linux搭建这种websocket环境,网上也有很方法
  4. Layim如何修改默认展示的聊天记录的条数

因为layim默认展示20条聊天记录,多的话,以前的记录会被折叠

可以修改lay\modules\mobile.js文件 查找“c=20”后面的条数修改为你需要展示的条数,然后清除浏览器缓存即可(此方法适用于引入moblie的手机版js,pc端可去试试其他文件)

如若有误或者有其他问题请与我交流:2359582968(微信qq同号)