laravel & pusher 私聊系统的实现

由于再做一个课程大作业,想要实现一个web私聊的系统,于是去google & baidu 搜索了很多文章来看,但是对于初入门的我并不是很了解其体系架构以及laravel 与 pusher之间的联系,laravel的官方文档也只是告诉怎么用,并没有一个详细的解释,于是头疼了一个星期。接下来就说说我是怎么实现这个功能的。
ps. 这个只是我自己这么觉得。。不一定是对的,但是功能是可以实现的
先上图,此图是我对其理解。

由图可以看到 pusher 在整个交互中处于laravel 之下客户端之上的中间层次。

  1. 客户端Client1想要发送信息给Client2,于是通过post一个chatData{fromid,toid,msg} 到服务器去处理。
  2. laravel通过路由交给 chatController@DeliverMessage 处理。
  3. 在 chatController@DeliverMessage 中,新建事件chatMessageEvent 并使用event()这个功能发布至pusher 。
  4. pusher 推送消息至Client2,Client2 通过监听相应 channel 来获取信息。

以上是laravel pusher的大致流程。
ps.Pusher 是通过 channel 来指定要发送的数据发送到哪儿的,比如Client1创建了一个叫做chat.1的通道,Client2想要发送msg到Client1,pusher就会把消息通过chat.1这个通道广播出去,于是Client1就监听到了信息。
pps.我的解决方案是为每个用户开一个channel,以id区分,只需要广播到相应频道即可接收信息。

下面来讲讲具体实现,在我的大作业上,我是通过laravel5.5 + vue +axios + pusher实现的。
另外由于我的分工是写后端的,所以对于vue并不很了解,因此vue端只贴代码,具体vue中的操作请参照vue官方文档。

客户端通过vue实现,其所有文件在 你创建的项目\resources\assets\js
后台文件自然是在 你创建的项目\app

  1. 准备工作
    后台
    composer require pusher/pusher-php-server
    去pusher官网申请账号(似乎需要科学上网)
    得到
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
//填入.env中 并更改广播驱动为pusher 默认队列为sync
BROADCAST_DRIVER=pusher
QUEUE_DRIVER=sync

前端
cnpm install pusher-js --save
cnpm install laravel-echo --save

  1. 客户端 post ChatData 到 服务器。
 postChatData(){
      axios.post('/chat',{
        from:id,
        to:'1', /*这里是因为页面没有写获取到对方id的方法,所以暂时硬编码进去以便测试*/
        msg:'This is a chat data.',
      }).then(function(response){
            console.log(response.data);
          });
    }
  1. 服务端 Route 、Controller 、Event 、Model
    php artisan make:controller chatController来创建Controller
//你创建的项目\routes\web.php
Route::post('/chat','chatController@deliver');

//chatController@deliver
public function deliver(Request $request){
        $from=$request->from;
        $to=$request->to;
        $msg=$request->msg;

/* 这里是因为上面vue中发送给谁硬编码了,所以在这里通过判断更改*/
        if($from===1) $to='2';
        else $to='1'; 

        $cmsg=new chatMessage;
        $cmsg->fid=$from;
        $cmsg->tid=$to;
        $cmsg->msg=$msg;
        $cmsg->save();

        event(new chatMessageEvent($cmsg));
        return response()->json(['from' => $from,'to'=>$to,'msg'=>$msg]);
    }

php artisan make:migration chat_message_table

\\在创建的chat_message_table文件中
public function up(){
        Schema::create('chat_messages', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('fid');
            $table->integer('tid');
            $table->text('msg');
            $table->timestamps();
        });
}

php artisan make:model chatMessage

// App\chatMessage.php
class chatMessage extends Model
{
   protected $table = 'chat_messages';
   protected $primaryKey='id';
   protected $fillable = [
      'fid','tid','msg',
   ];
}

php artisan make:event chatMessageEvent

/* App\Events\chatMessageEvent.php
    详细信息见laravel 广播 官方文档*/
...
use App\chatMessage;

//注意 这里需要自己继承 ShouldBroadcast 接口
class chatMessageEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $chatMessage; //这是广播的内容
   
    public function __construct($chatMessage) {
        $this->chatMessage=$chatMessage;
    }

    public function broadcastOn() {
        return new Channel('chat.'.$this->chatMessage->tid);
    }
}
  1. 客户端接受消息
\\bootstrap.js
...
 import Echo from 'laravel-echo'

 window.Pusher = require('pusher-js');

 window.Echo = new Echo({
     broadcaster: 'pusher',
     key: 'xxxxxx', //之前准备时得到的key
     cluster:'ap1', //在pusher中选择的服务器
     encrypted:true //是否加密
 });
//在你的vue文件中 获取到自己的id后 创建监听
window.Echo.channel('chat.'+id)
              .listen('chatMessageEvent',(data)=>{
                console.log(data);
                /*返回是否接收信息 此处同样需要定义路由
                    为了能够解决离线问题,我选择在接收到后返回一个收到信息
                    并删除数据库中此条记录
                    在用户再次登陆时区数据库中数据发送
                */
                axios.post('/respchat',{
                  hasReceived:true,
                  id:data.chatMessage.id,
                }).then(function(response){
                  console.log(response.data);
                });
              });

至此,你可以通过创建用户登录获取id来创建channel 发送并接受pusher所推送的信息。

第一次写这类文章,难免有所疏漏或错误,希望看到这篇文章的大神们能够指出,万分感谢!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,924评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,902评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,716评论 0 239
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,783评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,166评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,510评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,784评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,476评论 0 196
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,196评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,459评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,978评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,321评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,964评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,046评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,803评论 0 193
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,530评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,420评论 2 265

推荐阅读更多精彩内容