基于 Laravel + Pusher + Vue 通过事件广播构建实时聊天室应用


前言:学院君之前有说过要整理出一篇事件广播手把手教程,今天终于兑现了,本教程基于 Laravel + Pusher + Vue,以事件广播作为核心技术,从零开始让你在几分钟内即可搭建起一个实时聊天室应用。不多废话,直接上手吧。

应用初始化

安装配置

首先还是通过 Composer 安装一个全新的聊天室应用:

由于要用到事件广播,所以需要取消 config/app.php 中广播服务提供者前面的注释:

修改 .envBROADCAST_DRIVER 配置项为 pusher

尽管 Laravel 开箱支持 Pusher,但是我们还是需要安装对应的 PHP SDK:

设置 Pusher 凭证信息

访问 Pusher 官网,注册并登录到用户后台,创建一个新的 Channels App:

创建完成后即可在跳转页面中获取到 App Keys 相关信息:

将对应字段填充到聊天室应用根目录下的 .env 相应配置项即可。

前端资源初始化

我们使用 Laravel Mix 来编译前端 CSS 和 JavaScript:

此外,Laravel 还提供了 JavaScript 库 Laravel Echo 来订阅和监听事件:

安装完成,还要告知 Laravel Echo 使用 Pusher,Laravel 已经在 resources/assets/js/bootstrap.js 中为我们提供了该实现,只不过默认注释起来了,只需要取消这段注释即可:

用户认证脚手架代码

我们设定只有登录用户才能进入聊天室进行聊天,为了简化流程,我们使用 Laravel 默认的用户认证功能:

上述命令会为我们生成用户认证系统所必须的路由、视图、控制器等代码。在功能生效之前,还需要运行数据库迁移命令生成对应数据表,编辑 .env 中数据库相关配置项,保证可以正确连接上数据库,然后运行以下命令:

至此,应用初始化准备工作已完成,下面开始编写业务代码。

业务代码实现

消息模型

首先要为发送的消息创建一个模型类及其对应数据库迁移文件:

在新生成的 app/Messaage 模型类中新增下面这行代码以方便批量赋值:

然后在 databases/migrations 目录下编写刚生成的 messages 对应迁移文件的 up 方法:

最后执行迁移命令生成数据表 messages

用户与消息的关联关系

很显然,用户与消息之间是一对多的关系,在 User 模型类中新增关联方法:

接下来在 Message 模型类中定义与之相对的关联关系:

控制器代码

创建控制器 ChatsController 实现具体业务逻辑:

编写刚生成的控制器类 app/Http/Controllers/ChatsController 代码如下:

该控制器提供了三个业务方法,index 用于显示聊天室视图,fetchMessages 用户获取所有消息,sendMessage 用于发送消息。

注册应用路由

对应地,我们在 routes/web.php 中注册三个路由:

从注册路由中移除 /home 路由,相应地,需要把 app/Http/Controllers/Auth/LoginController.phpapp/Http/Controllers/Auth/RegisterController.php 中的 $redirectTo 属性进行调整:

聊天室视图

对于聊天室视图代码,我们基于 Bootsnipp 聊天室代码片段 稍作调整。首先创建 resources/views/chat.blade.php

该视图用于展示聊天室主体页面。注意到我们在视图中使用了一些 Vue 组件,chat-messages 组件用于显示所有聊天信息,chat-form 组件用于发送消息,稍后会给出这些组件代码。

在编写 Vue 组件之前,我们在 resources/views/layouts/app.blade.php 模板中为 chat 视图添加一些样式代码(添加到 标签之前):

接下来在 resources/assets/js/components 中创建 ChatMessages.vue 组件:

然后在同一目录下创建 ChatForm.vue 组件:

最后我们需要将这两个组件注册到位于 resources/assets/js/app.js 中的 Vue 根实例中:

广播消息发送事件

为了在聊天室中进行实时交互,需要广播某些事件,在本例中,我们会在用户发送消息时触发 MessageSent 事件:

编写 app/Events/MessageSent 事件类代码如下:

由于只有登录用户才能访问我们的应用,所以我们定义了一个私有的频道 chat,只有登录用户才能连接上它。

接下来,我们需要修改 ChatsControllersendMessage() 来广播 MessageSent 事件:

然后在 routes/channels.php 中授权当前登录用户可以监听该私有频道:

现在,当一条消息发送后,MessageSent 事件就会被广播到 Pusher,使用 toOthers() 是为了将消息发送者从广播接收者中排除。

监听消息发送事件

MessageSent 事件在服务端被广播后,需要在客户端监听这个事件以便将最新发送消息更新到聊天室消息流中,我们可以通过在 resources/assets/js/app.js 中定义的 created() 方法中添加如下代码片段来实现这一功能:

我们通过 Laravel Echo 连接到 chat 频道监听 MessageSent 广播事件,如果有新消息则将其推送到当前聊天室消息流中显示。

在正式测试聊天室应用之前,还需要运行以下命令通过 Laravel Mix 来编译前面编写的 JavaScript 代码:

使用示例演示

完成上述所有业务代码编写工作后,接下来就是见证工作成果的时候了,在项目根目录下运行如下命令启动应用:

然后在浏览器通过 http://127.0.0.1:8000/ 访问应用,由于系统需要登录后才能访问,所以首先会跳转到登录页面,我们需要先注册一个新用户(学院君1),注册成功后页面即跳转到聊天室页面,我们发送一条测试消息:

为了测试多个用户聊天的效果,打开另一个浏览器或者在当前浏览器新开一个隐身窗口,还是重复上面的访问注册步骤(这次注册用户为 学院君2),注册成功后跳转到聊天室页面,看到的效果和上图一样,我们发条消息试试:

可以看到两个窗口消息是同步的,所以已经达到我们预期的实时聊天效果,实现了通过事件广播构建实时聊天室的功能:

棒棒哒!

声明:Pusher 是一个收费服务,免费版本最大支持同时 100 个连接,以及每天20万消息量,拿来作为开发测试完全没问题。

<< 上一篇: 在 Laravel 项目中集成 Swagger 扩展包为 Laravel API 生成接口文档并对接口进行测试

>> 下一篇: 由浅入深:基于 Laravel Broadcast 实现 WebSocket C/S 实时通信