一个基于 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
本帖由系统于 6年前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 13

学习了

7年前 评论

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

7年前 评论
jcc123

@ccwd 查看下日志

7年前 评论

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

7年前 评论

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

6年前 评论
jcc123

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

6年前 评论

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

6年前 评论
jcc123

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

6年前 评论

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

6年前 评论
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年前 评论

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