zoukankan      html  css  js  c++  java
  • laravel5.5事件广播系统实例laravel-echo + redis + socket.io

    本教程会详细介绍配置的方法,以给全体用户发送通知为例。

    1. 广播配置说明

    1.1 广播驱动配置

    文件位置 config/broadcasting.php

    <?php
    
    return [
        'default' => env('BROADCAST_DRIVER', 'null'),
    
        'connections' => [
    
            'pusher' => [
                'driver' => 'pusher',
                'key' => env('PUSHER_APP_KEY'),
                'secret' => env('PUSHER_APP_SECRET'),
                'app_id' => env('PUSHER_APP_ID'),
                'options' => [
                    //
                ],
            ],
    
            'redis' => [
                'driver' => 'redis',
                'connection' => 'default',
            ],
    
            'log' => [
                'driver' => 'log',
            ],
    
            'null' => [
                'driver' => 'null',
            ],
    
        ],
    
    ];
    

    可以看到Laravel自带了4个广播驱动器 pusher, redis, log, null

    1.2 注册服务提供器

    服务提供器位置:AppProvidersBroadcastServiceProvider

    <?php
    
    namespace AppProviders;
    
    use IlluminateSupportServiceProvider;
    use IlluminateSupportFacadesBroadcast;
    
    class BroadcastServiceProvider extends ServiceProvider
    {
        public function boot()
        {
            Broadcast::routes();
    
            require base_path('routes/channels.php');
        }
    }
    

    你只需在 config/app.php 配置文件的 providers 数组中取消对该提供者的注释即可

    2. 驱动器配置

    这里采用 redis + soocket.io 的组合

    2.1 安装predis

    如果你使用 Redis 广播器,请安装 Predis 库:

    composer require  predis/predis "~1.0"
    

    2.2. 配置服务端

    这里采用社区驱动维护的项目 tlaverdure/laravel-echo-server,这是一个使用socket.io来支持laravel广播的nodejs服务器。当运行后会将socket.io客户端js代码暴露在一个标准的的url中。我们需要在我们的项目中(视图文件)引入这个地址。

    2.2.1 安装方法

    npm install -g laravel-echo-server  # 这里是全局安装
    

    2.2.2 初始化服务端

    我是这样选择初始化配置的。可以根据自己情况改变

    $ laravel-echo-server init 
    ? Do you want to run this server in development mode? Yes
    ? Which port would you like to serve from? 6001
    ? Which database would you like to use to store presence channel members? redis
    ? Enter the host of your Laravel authentication server. archerwong.cn
    ? Will you be serving on http or https? http
    ? Do you want to generate a client ID/Key for HTTP API? Yes
    ? Do you want to setup cross domain access to the API? No
    appId: c953434932b06864
    key: 551440289d2d41c81e87d55c1d0217e5
    Configuration file saved. Run laravel-echo-server start to run server.
    
    
    

    2.2.3 运行服务端

    $ laravel-echo-server start
    
    L A R A V E L  E C H O  S E R V E R
    
    version 1.3.6
    
    ⚠ Starting server in DEV mode...
    
    ✔  Running at localhost on port 6001
    ✔  Channels are ready.
    ✔  Listening for http events...
    ✔  Listening for redis events...
    
    Server ready!
    

    检测下socket.io客户端url地址是否可访问

    http://your_host_address:6001/socket.io/socket.io.js
    

    可访问,并内容类似于以下则说明服务器可用

    !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(......
    

    2.3 配置客户端

    2.3.1 安装laravel-echo

    Laravel Echo 是一个 JavaScript 库,它使得订阅频道和监听由 Laravel 广播的事件变得非常容易。

    npm install laravel-echo --save  # 安装laravel-echo 并记录package.json
    

    2.3.2 创建一个全新的 Echo 实例

    官方说法是在resources/assets/js/bootstrap.js文件底部引入是个好地方,打开该文件加入下面内容

    import Echo from "laravel-echo"
    
    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.hostname + ':6001'
    });
    

    其实如果使用blade模板,没有使用vue等前端,我们需要在入口视图定义id="app"挂载点,否则打包后会发现#app未定义,并且会打包进去vue等我们不需要的内容,文件也会变大,

    简单粗暴一点可以修改resource/assets/js/app.js,直接打包我们需要的内容

    import Echo from "laravel-echo"
    
    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.hostname + ':6001'
    });
    

    2.3.3 使用laravel-mix打包

    修改 webpack.mix.js

    let mix = require('laravel-mix');
    
    mix.js('resources/assets/js/app.js', 'public/js');
    //   .sass('resources/assets/sass/app.scss', 'public/css');
    

    生成

    npm run dev
    

    这样我们就得到了一个压缩的public/app.js文件

    2.3.4 在视图引入各项

    • 引入csrf

    Laravel Echo 会需要访问当前会话的 CSRF 令牌,可以在应用程序的 head HTML 元素中定义一个 meta 标签:

    <meta name="csrf-token" content="{{ csrf_token() }}">
    
    • 引入Socket.IO JavaScript 客户端库
    <script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
    
    • 实例化Echo
    <script src="/js/app.js"></script>
    <script>
        <!--上面app.js已经进行了Echo的实例化,然后应该使用实例化的Echo进行广播事件的监听-->
        console.log(Echo);
    </script>
    

    到此为止,我们基本的配置已经完成,Echo的前端监听等后面讲到再补充。

    3. 后端事件

    3.1 前提是配置和运行队列侦听器

    修改.env 中的配置

    QUEUE_DRIVER=redis
    

    运行队列监听

    php artisan queue:work
    

    3.2 编写事件

    创建文件 app/Events/TestBroadcastingEvent.php, 内容如下

    <?php
    
    namespace AppEvents;
    
    use IlluminateBroadcastingChannel;
    use IlluminateQueueSerializesModels;
    use IlluminateBroadcastingPrivateChannel;
    use IlluminateBroadcastingPresenceChannel;
    use IlluminateFoundationEventsDispatchable;
    use IlluminateBroadcastingInteractsWithSockets;
    use IlluminateContractsBroadcastingShouldBroadcast;
    use AppHttpModelNotice;
    
    class TestBroadcastingEvent implements ShouldBroadcast
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
    
        public $notice;
    
        /** 
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct(Notice $notice)
        {   
            $this->notice = $notice;
        }
    
        /** 
         * Get the channels the event should broadcast on.
         *
         * @return IlluminateBroadcastingChannel|array
         */
        public function broadcastOn()
        {   
            return new Channel('notice');
    
        }
    
    }
    
    

    3.3 分发事件

    <?php
    
    namespace AppHttpControllersHome;
    
    use AppHttpModelNotice;
    use AppEventsTestBroadcastingEvent;
    
    class TestController extends CommonController
    {
        public function send($id)
        {   
            //当需要给全体发通知的时候触发
            $notice = Notice::find($id);
            event(new TestBroadcastingEvent($notice));
        }
    
    }
    
    

    4. 前端监听

    应该还记得前面已经实例化了Echo,现在就是要用这个Echo进行监听,实现广播功能

    <script src="//{{ Request::getHost() }}:6001/socket.io/socket.io.js"></script>
    <script src="/js/app.js"></script>
    <script>
        <!--上面app.js已经进行了Echo的实例化,然后应该使用实例化的Echo进行广播事件的监听-->
        console.log(Echo);
        Echo.channel('notice')
            .listen('TestBroadcastingEvent', (e) => {
                // 如果有广播过来你可以进行逻辑操作,比如给用户一个通知
                console.log(e);
                console.log(e.order);
            });
    

    5. 查看结果

    触发send()方法进行测试,控制台输出如下内容

    {notice: {…}, socket: null}
    {id: 1, content: "感谢你的仔细阅读,期待共同进步!", created_at: null, updated_at: null}
    

    发现我们后端TestBroadcastingEvent事件类的notice属性被传递过来了,你就可以收到我的感谢了。

    6. 整体结构

    后端: laravel-echo-server服务器 (通过url地址暴露 socket.io.js)=> 编写并触发广播事件

    前端: laravel-echo库 + 后端暴露的socket.io.js => 实例化Echo => 监听广播事件

  • 相关阅读:
    JSONObject的问题- 在用JSONObject传参到controller接收为空白和JSONArray添加json后转string不正确
    SpringContextHolder使用报错:applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder
    MQ报错Waiting for workers to finish.Stopping container from aborted consumer.Successfully waited for workers to finish.
    nacos的docker启动
    问题总结
    ubuntu docker中文乱码问题
    你该用HTTP2了
    Redis哨兵(Sentinel)模式快速入门
    Redis主从复制的原理
    Redis持久化的原理及优化
  • 原文地址:https://www.cnblogs.com/redirect/p/8658800.html
Copyright © 2011-2022 走看看