Laravel 即时应用的一种实现方式 | Laravel | Laravel China 社区


本站和网页 https://learnku.com/laravel/t/2566/an-implementation-of-laravel-real-time-application 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

Laravel 即时应用的一种实现方式 | Laravel | Laravel China 社区
Laravel
话题列表
社区 Wiki
优质外文
招聘求职
Laravel 实战教程
社区文档
登录
注册
Laravel
首页
Laravel
Go
PHP
Vue.js
Python
Java
MySQL
Rust
LK
Elasticsearch
F2E 前端
Server
程序员
Database
DevTools
Computer Science
手机开发
AdonisJS
社区
Wiki
教程
Laravel 实战教程首页
《L01 Laravel 教程 - Web 开发实战入门》
《L02 Laravel 教程 - Web 开发实战进阶》
《L03 Laravel 教程 - 实战构架 API 服务器》
《L04 Laravel 教程 - 微信小程序从零到发布》
《L05 Laravel 教程 - 电商实战》
《L06 Laravel 教程 - 电商进阶》
《LX1 Laravel / PHP 扩展包视频教程》
《LX2 PHP 扩展包实战教程 - 从入门到发布》
《L07 Laravel 教程 - Laravel TDD 测试实战》
《LX3 Laravel 性能优化入门》
《LX4 Laravel / PHP 五分钟视频》
文档
社区文档首页
《Laravel 中文文档》
《Laravel 速查表》
《PHP 代码简洁之道》
《Laravel 编码技巧》
《Dcat Admin 中文文档》
《Laravel Nova 中文文档》
《Lumen 中文文档》
《Dingo API 中文文档》
《 Laravel 项目开发规范》
《构建 Laravel 开发环境》
登录
注册
微信登录
Laravel 即时应用的一种实现方式
71
20
分享
20405
创建于 6年前
即时交互的应用
在现代的 Web 应用中很多场景都需要运用到即时通讯,比如说最常见的支付回调,与三方登录。这些业务场景都基本需要遵循以下流程:
客户端触发相关业务,并产生第三方应用的操作(比如支付)
客户端等待服务端响应结果(用户完成第三方应用的操作)
第三方应用通知服务端处理结果(支付完成)
服务端通知客户端处理结果
客户端依据结果做出反馈 (跳转到支付成功页面)
在过去,为了实现这种即时通讯,能让客户端正确响应处理结果,最为常用的技术就是轮询,因为 HTTP 协议的单向性,客户端只能一遍一遍的主动询问服务端的处理结果。这种方式有显见的缺陷,占用服务端资源不说,还不能实时获得服务端处理结果。
现在,我们可以使用 WebSocket 协议来处理实时交互,它是一种双向协议,允许服务端主动推送信息到客户端。本篇我们将借助 Laravel 强大的事件系统来构建实时的交互。你将需要用到以下知识:
Laravel Event
Redis
Socket.io
Node.js
Redis
在开始之前,我们需要开启一个 redis 服务,并在 Laravel 应用中进行配置启用,因为在整个流程中,我们需要借助 redis 的订阅和发布机制来实现即时通讯。
Redis 是一个开源高效的键值对存储系统。它通常作为一个数据结构服务器来存储键值对,它可以支持字符串,散列,列表,集合和有序结合。在 Laravel 中使用 Redis 你需用通过 Composer 来安装 predis/predis 包文件。
配置
Redis 在应用中的配置文件存储在 config/database.php,在这个文件中,你可以看到一个包含了 Redis 服务信息的 redis 数组:
'redis' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'port' => 6379,
'database' => 0,
],
如果你修改了 redis 服务的端口,请保持配置文件中的端口一致。
Laravel Event
这里我们需要借助 Laravel 强大的事件广播能力:
广播事件
很多现代化的应用中,会使用 Web Sockets 来实现实时交互的用户接口。当一些数据在服务端变更时,一条消息会通过 WebSocket 连接来传递到客户端进行处理。
为了帮助你构建这种类型的应用。Laravel 使通过 WebSocket 连接进行广播事件变的非常简单。Laravel 允许你广播事件来共享事件的名称到你的服务端和客户端的 JavaScript 框架。
配置
所有的事件广播配置选项都被存储在 config/broadcasting.php 配置文件中。Laravel 附带了几种可用的驱动如 Pusher,Redis,和 Log,我们将使用 Redis 作为广播驱动,这里需要依赖 predis/predis 类库。
由于默认的广播驱动使用的是 pusher,所以我们需要在 .env 文件中设置 BROADCAST_DRIVER=redis。
我们创建一个 WechatLoginedEvent 事件类用来在用户扫描微信登录后进行广播:
<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class WechatLoginedEvent extends Event implements ShouldBroadcast
use SerializesModels;
public $token;
protected $channel;
/**
* Create a new event instance.
* @param string $token
* @param string $channel
* @return void
*/
public function __construct($token, $channel)
$this->token = $token;
$this->channel = $channel;
/**
* Get the channels the event should be broadcast on.
* @return array
*/
public function broadcastOn()
return [$this->channel];
/**
* Get the name the event should be broadcast on.
* @return string
*/
public function broadcastAs()
return 'wechat.login';
其中你需要注意 broadcastOn 方法应返回一个数组,它表示所需广播的频道,而 broadcastAs 返回的是一个字符串,它表示广播所触发的事件,Laravel 默认的是返回事件类的全类名,这里是 App\Events\WechatLoginedEvent.
最重要的是你需要手动的让该类实现 ShouldBroadcast 契约。Laravel 在生成事件时,已经自动添加了该命名空间,该契约只约束 broadcastOn 方法。
事件完成接下来就是触发事件了,简单的一行代码就可以:
event(new WechatLoginedEvent($token, $channel));
这个操作会自动的触发事件的执行并将信息广播出去。该广播操作底层借助了 redis 的订阅和发布机制。RedisBroadcaster 会将事件中的允许公开访问的数据通过给定的频道发布出去。如果你想对公开的数据拥有更多的控制,你可以在事件中添加 broadcastWith 方法,它应该返回一个数组:
/**
* Get the data to broadcast.
* @return array
*/
public function broadcastWith()
return ['user' => $this->user->id];
Node.js 和 Socket.io
对于发布出去的信息,我们需要一个服务来对接,让其能对 redis 的发布能够进行订阅,并且能把信息以 WebSocket 协议转发出去,这里我们可以借用 Node.js 和 socket.io 来非常方便的构建这个服务:
// server.js
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
app.listen(6001, function () {
console.log('Server is running!') ;
});
function handler(req, res) {
res.writeHead(200);
res.end('');
io.on('connection', function (socket) {
socket.on('message', function (message) {
console.log(message)
})
socket.on('disconnect', function () {
console.log('user disconnect')
})
});
redis.psubscribe('*', function (err, count) {
});
redis.on('pmessage', function (subscrbed, channel, message) {
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
这里我们使用 Node.js 引入 socket.io 服务端并监听 6001 端口,借用 redis 的 psubscribe 指令使用通配符来快速的批量订阅,接着在消息触发时将消息通过 WebSocket 转发出去。
Socket.io 客户端
在 web 前端,我们需要引入 Socket.io 客户端开启与服务端 6001 端口的通讯,并订阅频道事件:
// client.js
let io = require('socket.io-client')
var socket = io(':6001')
socket.on($channel + ':wechat.login', (data) => {
socket.close()
// save user token and redirect to dashboard
})
至此整个通讯闭环结束,开发流程看起来就是这样的:
在 Laravel 中构建一个支持广播通知的事件
设置需要进行广播的频道及事件名称
将广播设置为使用 redis 驱动
提供一个持续的服务用于订阅 redis 的发布,及将发布内容通过 WebSocket 协议推送到客户端
客户端打开服务端 WebSocket 隧道,并对事件进行订阅,根据指定事件的推送进行响应。
PS: 欢迎关注简书 Laravel 专题,也欢迎 Laravel 相关文章的投稿 :),作者知识技能水平有限,如果你有更好的设计方案欢迎讨论交流,如果有错误的地方也请批评指正,在此表示感谢 :)
本帖已被设为精华帖!
本帖由 Summer
于 6年前 加精
举报
DearMadMan
联合编辑
163 声望
Beautiful work by passionate people.
71 人点赞
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
推荐文章:
更多推荐...
分享创造
如何找到你的第一份远程工作与海外外包-远程工作篇(放了个TS全栈教学的广告,不喜欢立删...)
33
21
1个月前
翻译
如何在 Laravel 中创建一个简单的事件流?
19
12
3个月前
博客
我是如何把网站图片cdn流量成本压到全网最低(之一)的
32
28
3个月前
博客
🎈 Slow Admin - 使用Laravel和Amis快速构建你的后台
25
35
3个月前
博客
用Go实现支持多种协议的抓包工具——Shermie-Proxy
22
33
5个月前
分享创造
大佬的收藏夹
75
21
5个月前
讨论数量: 5
排序:
时间
投票
overtrue
管理员
1.5k 声望
PHP @ Tencent
赞,建议在前面描述一下使用场景,因为对于新手来讲直接看这些实现会有点懵
6年前
评论
评论
举报
DearMadMan
联合编辑
163 声望
@overtrue 这个确实是,需要实践才能理解。后续的文章会尽量描述一下相关场景 :smile: 谢谢超神的建议
6年前
评论
评论
举报
overtrue
管理员
1.5k 声望
PHP @ Tencent
@DearMadMan 么么哒
6年前
评论
评论
举报
小李世界
Laravel 8.x 译者
1.8k 声望
Doge 先锋 @ dogeow.com
用 redis 的方式感觉很不错啊
3年前
评论
评论
举报
cherryne
课程读者
21 声望
这跟laravel-Echo-server有啥区别?
1年前
评论
评论
举报
讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
<a href="javascript:;" class="mr-2 ui popover text-mute" data-html="黏贴或拖拽图片至输入框内皆可上传图片">
<a href="javascript:;" class="mr-2 ui popover text-mute hide-on-mobile" data-html="支持除了 H1~H6 以外的GitHub 兼容 Markdown">
支持 MD
帮助
关注本文
评论
DearMadMan
163 声望
纠错改进
社区赞助商
成为赞助商
社区赞助商
成为赞助商
关于 LearnKu
LearnKu 是终身编程者的修道场
做最专业、严肃的技术论坛
LearnKu 诞生的故事
资源推荐
《社区使用指南》
《文档撰写指南》
《LearnKu 社区规范》
《提问的智慧》
服务提供商
其他信息
成为版主
所有测验
联系站长(反馈建议)
粤ICP备18099781号-6
粤公网安备 44030502004330号
违法和不良信息举报
由 Summer 设计和编码 ❤
请登录
提交
忘记密码?
or
注册
第三方账号登录
微信登录
GitHub 登录
内容举报
匿名举报,为防止滥用,仅管理员可见举报者。
我要举报该,理由是:
垃圾广告:恶意灌水、广告、推广等内容
无意义内容:测试、灌水、文不对题、消极内容、文章品质太差等
违规内容:色情、暴利、血腥、敏感信息等
不友善内容:人身攻击、挑衅辱骂、恶意行为
科学上网:翻墙、VPN、Shadowsocks,政策风险,会被关站!
不懂提问:提问太随意,需要再做一遍《提问的智慧》测验
随意提问:提问没有发布在社区问答分类下
排版混乱:没有合理使用 Markdown 编写文章,未使用代码高亮
内容结构混乱:逻辑不清晰,内容混乱,难以阅读
标题随意:标题党、标题不释义
尊重版权:分享付费课程、破解软件(付费),侵犯作者劳动成果
其他理由:请补充说明
举报
取消