找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 651|回复: 0
打印 上一主题 下一主题

Laravel学习教程之广播模块详解

[复制链接]

2560

主题

2560

帖子

7622

积分

论坛元老

Rank: 8Rank: 8

积分
7622
跳转到指定楼层
楼主
发表于 2018-2-14 05:23:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

            前言
本文主要给大家介绍了关于Laravel广播模块的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍:
注意:本文是基于Laravel 5.4版本的路由模块代码进行分析书写;
简介

广播是指发送方发送一条消息,订阅频道的各个接收方都能及时收到消息;比如 A同学写了一篇文章,这时候 B同学在文章底下评论了,A同学在页面上是不用刷新就能收到提示有文章被评论了,这个本质上就是A同学收到了广播消息,这个广播消息是由B同学评论这个动作触发了发送广播消息;
在整个广播行为中,有一个重要的概念叫频道channel,频道的类型有

  
  • 公共频道public
      
  • 私有频道private
      
  • 存在频道presence

    移动端订阅了公共频道public,会直接提示成功;私有频道private和存在频道presence在进行订阅的过程中,会向服务器端发送权限验证,看是不是有权限可以订阅该频道;私有频道private和存在频道presence的区别在于,私有频道private能够接收其他成员发送的消息,而存在频道presence除此之外,还能够在用户的加入与离开时接收信息;
    广播适合以下场景:

      
  • 通知(Notification) 或 信号(Signal)
      
  • 通知是最简单的示例,也最经常用到。信号也可看作是通知的一种展现形式,只不过信号没有UI而已。
      
  • Activity Streams
      
  • Activity Streams(feeds)是社交网络的核心。如微信朋友圈的点赞和评论,A可以实时看到B的点赞,B可以实时看到A的评论。
      
  • 聊天
      
  • 聊天信息的实时显示

    模块组成

    Demo
    日志驱动
    配置
    .env文件修改或添加一行:BROADCAST_DRIVER=log;
    广播
    直接调用
    $manager = app(Illuminate\Broadcasting\BroadcastManager::class);
    $driver = $manager->connection();
    // 第一个参数是频道名,第二个参数是事件名,第三个参数是广播内容
    $driver->broadcast(['channel_1', 'channel_2'], 'login', ['message' => 'hello world']);
    因为是日志驱动,所以广播内容会写到框架配置的日志文件中,输出消息如下所示
    [2017-08-18 20:45:49] local.INFO: Broadcasting [login] on channels [channel_1, channel_2] with payload:
    {
    "message": "hello world"
    }
    监听事件广播
    这种调用方式,是当实现ShouldBroadcast接口的事件被触发时,则会进行广播操作;(同时,还有一个接口叫ShouldBroadcastNow,与ShouldBroadcast接口的不同在于,将实现ShouldBroadcastNow接口的事件放入队列中时,会被放入叫sync的队列中)
    举个例子,
    第一步,Illuminate\Auth\Events\Login事件是用户登录成功后会触发的事件,略作改动,让其实现广播功能;
    class Login implements ShouldBroadcast {
    ......

    // 定义事件被触发时,广播频道;此处定义名为 first-channel 的私有频道
    public function broadcastOn() {
      return [
       new PrivateChannel('first-channel'),
      ];
    }

    // 自定义广播名称;如果方法未定义,默认以类名为事件名,此处的默认值是 Illuminate\Auth\Events\Login
    public function broadcastAs() {
      return 'login';
    }
    }
    第二步,注册事件监听;在app/Providers/EventServiceProvider.php中修改:
    protected $listen = [
    ......
    'Illuminate\Auth\Events\Login' => [
      'App\Listeners\UserLogin',
    ],
    ];
    文件app/Listeners/UserLogin.php粗糙地实现了一下:
    class UserLogin {
    public function __construct() {}

    public function handle(Login $event){
      \Log::info('Do UserLogin Listener: I was Login');
    }
    }
    第三步,触发事件,发送广播;有好几种触发广播方式:
    直接事件触发
    event(new Illuminate\Auth\Events\Login($user, true));
    帮助函数broadcast,间接触发事件
    broadcast(new Illuminate\Auth\Events\Login($user, true));
    广播管理类,间接触发事件,直接广播
    $manager = app(Illuminate\Broadcasting\BroadcastManager::class);
    $manager->event(new Illuminate\Auth\Events\Login($user, true));
    广播管理类,间接触发事件,放入队列
    $manager = app(Illuminate\Broadcasting\BroadcastManager::class);
    $manager->queue(new Illuminate\Auth\Events\Login($user, true));
    Pusher驱动
    Pusher是一个第三方服务,服务器发送广播时,会向Pusher发送请求,再通过Pusher与浏览器或移动端保持的长连接进行数据交互;
    配置
    通过Pusher官网注册用户信息,获取属于自已的一套密钥信息,修改.env的配置文件;
    BROADCAST_DRIVER=pusher
    PUSHER_APP_ID=xxxxxxxxxxxxxxxxxxxxxx
    PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxxxx
    PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxx
    准备工作
    事件监听
    后台的事件监听还是采用"日志驱动"部分的登录例子;
    前端
    前端页面引入以下代码:
    如果订阅的是公共频道,则不会向服务器端请求权限检查;如果是私有频道(频道名是以private-开头)或存在频道(频道名是以presence-开头),则会发出权限检查请求;对应的后端需要定义私有频道和存在频道的权限;
    频道权限定义
    频道的权限定义是在routes/channels.php里;此处笔者为first-channel频道定义权限回调函数:
    Broadcast::channel('first-channel', function ($user) {
      return (int) $user->id === 1;
    });
    有读者会疑问,前端页面订阅的频道不是private-first-channel吗?怎么后端只定义first-channel频道的权限呢?那是因为,后端定义的频道假设是A,那么在Pusher及浏览器端或移动端传递的私有频道名为private-A,存在频道则会是presence-A;
    广播
    直接广播
    $manager = app(Illuminate\Broadcasting\BroadcastManager::class);
    $driver = $manager->connection();
    // socket 参数是广播私有频道时排除的 socket, 每个浏览器端或者移动端在建立 websocket 时都会被分配一个 socket_id
    $driver->broadcast(['private-first-channel'], 'login', ['user' => ['name' => 'hello'], 'socket' => '5395.4377611']);
    间接广播
    参考“日志驱动”提及的间接广播方式;
    如果要发送排我广播(也就是除了当前请求的这个客户端不收到广播消息),则需要以下条件:

      
  • 事件使用Illuminate\Broadcasting\InteractsWithSockets trait;
      
  • 前端发送过来的请求头部要携带X-Socket-ID信息;
      
  • 事件触发执行broadcast(new Illuminate\Auth\Events\Login($user, true))->toOthers();

    Redis驱动
    配置
    .env文件修改或添加一行:BROADCAST_DRIVER=redis;
    广播
    原理是同样在后端部署一个Socket.IO服务器,Laravel框架会发布消息到Socket.IO服务器上,由Socket.IO服务器同浏览器端或者移动端保持长连接;
    这部分笔者尚未demo,网上入门资料还是挺多的,知道原理,这部分动作上手就容易多了;
    总结
    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
    附录
    同类型的文章可参考以下,加深了解:

      
  • Laravel学院 事件广播基础知识
      
  • Pusher 的认识

                
                
    您可能感兴趣的文章:
  • Laravel中的Auth模块详解
  • Laravel学习教程之路由模块
  • Laravel学习教程之本地化模块
  • Laravel学习教程之View模块详解
  • 基于Laravel实现的用户动态模块开发
            
  • 分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    用户反馈
    客户端