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所推送的信息。

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

你可能感兴趣的:(laravel & pusher 私聊系统的实现)