使用 Laravel 广播事件实现基于 Socket.io 的实时消息通知

本文将基于 Laravel 5.5 + Vuejs 2.5.2 介绍使用 Laravel-echo-server.jsLaravel-echo.js 实现的 socket 服务

前置条件

开始使用

  • 指定事件广播驱动
    修改.env 配置项 BROADCAST_DRIVERredis

  • 创建消息通知

    确保 User Model 使用了 Notifiable 的 Trait

    php artisan make:notification TestNotification

  • 编辑 TestNotification

    修改 via 方法 return ['broadcast']

    因为 toArray 会同时被解析到 database , 而我们的通知可能和数据库中的存储不太一样,所以单独使用其 broadcast

    增加 toBroadcast 方法

    public function toBroadcast($notifiable)
    {
        return new BroadcastMessage([
            'message' => $this->data['message']
        ]);
    }

    完整的代码如下

    class Test extends Notification implements ShouldQueue
        {
                use Queueable;
    
                public $data;
    
                public function __construct($data = [])
                {
                        $this->data = $data;
                }
    
                public function via($notifiable)
                {
                        return ['broadcast'];
                }
    
                public function toBroadcast($notifiable)
                {
                        return new BroadcastMessage([
                                'message' => $this->data['message']
                        ]);
                }
        }
  • 安装 socket 服务端
    npm install -g laravel-echo-server
    安装完成后,在项目根目录执行 laravel-echo-server init 生成配置文件 , 具体参考 Laravel-echo-server
    最后,生成的文件大概类似:

    {
    "authHost": "http://sickle.dev",
    "authEndpoint": "/broadcasting/auth",
    "database": "redis",
    "databaseConfig": {
        "redis": {
            "port" : "6379",
            "host" : "127.0.0.1",
            "db" : 5
        },
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },
    "devMode": true,
    "host": null,
    "port": "6001",
    "protocol": "http",
    "socketio": {},
    "sslCertPath": "",
    "sslKeyPath": "",
    "sslCertChainPath": "",
    "sslPassphrase": "",
    "apiOriginAllow": {
        "allowCors": true,
        "allowOrigin": "http://localhost:1024",
        "allowMethods": "GET, POST",
        "allowHeaders": "Origin, Content-Type, X-Auth-Token, X-Requested-With, Accept, Authorization, X-CSRF-TOKEN, X-Socket-Id"
    }
    }

    可以参考我的配置,其中 authHost 为你当前项目的域名,allowOrigin 为允许跨域的域名,开发时建议设成 * 号

最后,执行 laravel-echo-server start 开启 socket 服务端

以下为前端部分

  • 安装 echo 客户端

为简单起见,我们使用一个第三方 vuevue-echo
main.js 里导入这个包

import Echo from 'vue-echo'
if(typeof io === 'function'){
    Vue.use(Echo, {
        broadcaster: 'socket.io',
        host: 'service.dev:6001',// 后端的URL + Laravel-echo-server 配置的端口号
        auth:{
            headers: {
                'Authorization': 'Bearer ' + getToken() // getToken前端自行实现
            }
        },
    });
}

在使用之前,最好将使用 socket 服务作为可选项。

然后,开启监听

if(typeof this.$echo !== 'undefined'){
    this.$echo.private(`App.Models.User.${this.user_info.user_id}`) //App.Models.User.1
    .notification((notification) => {
        if (notification.type === 'App\\Notifications\\TestNotification') { 
        console.log(notificaition) 
            let message = notification.message;
            let notify = this.$notify({
                title: '通知',
                dangerouslyUseHTMLString: true,
                message: message,
                type: 'info',
                onClick: () => {
                    notify.close();
                    this.$router.push({ name: 'xx' }) // 处理跳转到哪
                }
            });
        }
        })
}

如果不出意外,此时,已经可以监听到了。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由 Summer 于 6年前 加精
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 14

目前还没用过。不知道用在后台什么功能上面。后面折腾下

6年前 评论

太棒了
等等就來測試

6年前 评论
jacktop

还没写完吧?

6年前 评论

@839891627 一般来说消息的实时通知应用的最多

6年前 评论
jacktop

多谢楼主!

6年前 评论

请问下大神,这个方法能在小程序里面用吗?用wepy的话?

5年前 评论

@jacobsun this.$echo.private(App.Models.User.${this.user_info.user_id}) 那这种写法,在小程序里面应该怎么写呢?vue 有 use Echo 但是小程序里面的 websocket 跟这个不太一样吧?

5年前 评论

@dptms 小程序的socket没用过,但是方法应该一样。

自定义一个广播,简单的可以用redis的发布订阅功能,然后自定义一个socket server处理redis的消息,然后小程序里正常连接socket server,最后,注意下channel即可

5年前 评论
张浩浩浩浩

博主~ ,如果使用 Result API 风格设计的时候,1.该怎样写 2.怎么调试呢?不知道后续你有没有更新呐~

5年前 评论

Laravel-echo-server在服务器怎么部署呢?

5年前 评论
张浩浩浩浩
L A R A V E L  E C H O  S E R V E R

version 1.5.0

⚠ Starting server in DEV mode...

✔  Running at localhost on port 6001
✔  Channels are ready.
✔  Listening for http events...
✔  Listening for redis events...

Server ready!

您好,配置成功了。请问 controller 接口代码 怎么使用,有没有 demo 可以借鉴一下?大神

5年前 评论

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