天天看點

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同号)