一个基于 Laravel5.4+Vue+Redis 实时聊天的小 demo

一个基于Laravel+Vue+Redis 实时聊天的小demo

这篇是基于一个基于 Laravel5.4+Vue+Pusher 实时聊天的小 demo

当然也可以独立出来,只需要把驱动换成 Redis 就可以了

GitHub 直达

https://github.com/jplhomer/laravel-realtime-chat-demo

git

git clone https://github.com/jplhomer/laravel-realtime-chat-demo project

由于 GitHub 是基于 Pusher 的 所以安装之前需要一些修改

进入 composion.json

去掉 "pusher/pusher-php-server": "^2.6"

增加 "predis/predis": "^1.1"

然后 composer 安装

cd project 

composer install

配置数据库及 key

cp .env.example .env

art key:generate

配置驱动

BROADCAST_DRIVER=redis

迁移

art migtate

然后进入 package.json

去掉 "pusher-js": "^4.0.0"

yarn 或 npm 安装

yarn 

npm

yarn 或者 npm 打包

yarn run dev

npm run dev  

由于 Redis 使用的 Socket.IO 因此需要配置客户端 Socket.io 和服务员端 Socket.io

客户端 Socket.IO

进入 bootstrap.js

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: 'http://yourdomain.app:6001'
});

进入 app.blade.php head 中增加

<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>

服务端 laravel-echo-server

yarn add laravel-echo-server

或者 npm install laravel-echo-server

安装完成后 生成服务端的配置文件 启动后会读取这个配置文件

laravel-echo-server init

我的配置文件

{
    "authHost": "http://delo.app",
    "authEndpoint": "/broadcasting/auth",
    "clients": [],
    "database": "redis",
    "databaseConfig": {
        "redis": {},
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": false,
    "host": "delo.app",
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "sslCertPath": "",
    "sslKeyPath": ""
}

如果不运行 laravel-echo-server init 的话 可以新建一个 laravel-echo-server.json 的文件 复制上面的内容进去 修改成你的主机就可以了
最后在 app.blade.php 中引入

    <script src="//yourdomain:6001/socket.io/socket.io.js"></script>

启动

            laravel-echo-server start

file

ok 最后注册两个账号开始实验吧

file

你可能发现 在一个浏览器每刷新一次后,另一个浏览器的在线数都会加 1 ,但是用 pusher 的话就不会出现这个问题(这是为什么?)。奇怪

如何解决呢 其中走了好多弯路

刚开始的时候 想的是数组去重的方法

在 app.js 中你会发现

Echo.join('chatroom')
            .here((users) => {
                this.usersInRoom = users;
            })
            .joining((user) => {
                this.usersInRoom.push(user);
            })
            .leaving((user) => {
                this.usersInRoom = this.usersInRoom.filter(u => u != user)
            })
            .listen('MessagePosted', (e) => {
                this.messages.push({
                    message: e.message.message,
                    user: e.user
                });
            });

本来想着百度一个数组的去重方法 像这样的

Array.prototype.unique = function(){
 var res = [];
 var json = {};
 for(var i = 0; i < this.length; i++){
  if(!json[this[i]]){
   res.push(this[i]);
   json[this[i]] = 1;
  }
 }
 return res;
}
var arr = [112,112,34,'你好',112,112,34,'你好','str','str1'];
alert(arr.unique());

但经过 leo 的指点 有个插件非常好用 lodash 安装后

只需这样

this.usersInRoom=_.uniq(this.usersInRoom)

接下来 又是一个奇怪的事情 console.log(this.usersInRoom) 发现新增加的竟然是一个对象。数组去重就不行了。

我厚着脸皮向 overtrue 发出了呼唤 。。

向超神简单的描述一番后。 超神说 "返回的应该是对象,可以考虑用 ID" 拨云见日

this.usersRoom=users

users 既然是对象的话,让它返回 id 就可以了

users 是在哪里返回的呢,在BroadcastServiceProvider发现

 require base_path('routes/channels.php');

进入 routes/channels.php

Broadcast::channel('chatroom', function ($user) {
    return $user;
});

修改为

Broadcast::channel('chatroom', function ($user) {
        return $user->id;
    });

ok 柳暗花明!

总结: 虽然写了基于 pusher 和 redis 广播的两个小 demo,但还是游离于配置层面。底层的东西还是朦朦胧胧的。但对于刚入门的新手来说,这是比较有用的。因为我比较喜欢,先把东西呈现出来,然后再去深入。

一个 demo 爱好者

本作品采用《CC 协议》,转载必须注明作者和本文链接
Make everything simple instead of making difficulties as simple as possible
本帖由系统于 7年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 13

学习了

7年前 评论

请教一下,聊天人数可以显示出来,但是发送消息的时候直接500错误.

7年前 评论
jcc123

@ccwd 查看下日志

7年前 评论

@jc91715 解决问题了,predis的问题,composer update 就可以了,谢谢了,学习到新东西了。

7年前 评论

请问一下哥。这个可以结合 小程序的 socket 来应用吗,也就是客户端是小程序,那边能引入<script src="//yourdomain:6001/socket.io/socket.io.js"></script>这样的东西吗?

7年前 评论
jcc123

@dptms 小程序不支持 script 引入吧

7年前 评论

@jcc123 那如果要跟小程序结合用 webosocket的话,这种广播是不是就不好使了呀?

7年前 评论
jcc123

@dptms 微信小程序内就封装了socket

7年前 评论

@jcc123 socket 服务端还是得自己写吧

7年前 评论
hankin

访问broadcasting/auth时, 状态码403 Forbidden,是哪里被禁止了?

6年前 评论

我想说就不能改一下filter么,改成这样不就行了:filter(u => u.id != user.id) :joy:

6年前 评论

求助:前后端分离的项目,采用的的JWT的认证。 怎么携带 token 给服务端?

服务端报错:

file

前端的代码:

file

6年前 评论
jcc123

@莫无季 添加

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: 'http://localhost:6001',
    auth:
    {
        headers:
        {
            'Authorization': 'Bearer ' + token
        }
    }
});

然后 在app / Providers / BroadcastServiceProvider.php

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Broadcast;

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
       // Broadcast::routes();
         Broadcast::routes( [ 'middleware' => [ 'api', 'jwt.auth' ] ] );
        require base_path('routes/channels.php');
    }
}
6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!