美文网首页laravel
Laravel+vue公有/私有广播实战

Laravel+vue公有/私有广播实战

作者: 一梦三四年lyp | 来源:发表于2020-05-07 18:44 被阅读0次

    背景:

    最近需要做个服务端消息推送的事情,首先就考虑到了Laravel自带的广播功能,它是利用redis的发布订阅功能和前端利用node.js实现的一套集合了Websocket 的功能

    前置条件:
    后端:

    1,安装redis扩展
          composer require predis/predis
    2,在config/app.php中打开注释:
          App\Providers\BroadcastServiceProvider::class,
    3,在.env中
        APP_URL=http://your_domain.com  #域名
        APP_NAME=YourAppName   #默认laravel即可
        QUEUE_CONNECTION=redis  #redis队列
        BROADCAST_DRIVER=redis  #broadcast的驱动使用redis
    

    前端:

    1,npm Install
    2,npm install -g laravel-echo-server #https://github.com/tlaverdure/laravel-echo-server
    3,npm install --save socket.io-client
    

    公有频道

    1,后端代码:

    <?php
    
    namespace App\Events;
    
    use Illuminate\Broadcasting\Channel;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Foundation\Events\Dispatchable;
    use Illuminate\Broadcasting\InteractsWithSockets;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
    
    class PublicEvent implements ShouldBroadcast
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public $msg = '';
        public function __construct($msg)
        {
            $this->msg = $msg;
        }
    
        /**
         * Get the channels the event should broadcast on.
         *
         * @return \Illuminate\Broadcasting\Channel|array
         */
        public function broadcastOn()
        {
            return new Channel('public');
        }
    
    //    public function broadcastWith()
    //    {
    //        return [
    //            'data' => 'this is public'
    //        ];
    //    }
    }
    
    

    2,前端代码

    <script>
    import Echo from 'laravel-echo'
    
    window.io = require('socket.io-client');
    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.hostname + ':6001',
    });
    
    window.Echo.channel('public')
        .listen('PublicEvent', (e) => {
            console.log(e);
        });
    </script>
    

    3,打开页面在console,即可以看到我们发送的数据

    {msg: "this is public", socket: null}
    msg: "this is public"
    socket: null
    __proto__: Object
    }
    

    私有频道

    PrivateEvent:

    <?php
    
    namespace App\Events;
    
    use App\Models\UserModel;
    use Illuminate\Queue\SerializesModels;
    use Illuminate\Broadcasting\PrivateChannel;
    use Illuminate\Foundation\Events\Dispatchable;
    use Illuminate\Broadcasting\InteractsWithSockets;
    use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
    
    class PrivateEvent implements ShouldBroadcast
    {
        use Dispatchable, InteractsWithSockets, SerializesModels;
    
        public $user;
        public $userId = '';
    
        /**
         * Create a new event instance.
         *
         * @return void
         */
        public function __construct(UserModel $user)
        {
    
            $this->user = $user;
            $this->userId = 3590;
    
            // dd('user.' . $this->user->u_id);
        }
    
        /**
         * Get the channels the event should broadcast on.
         *
         * @return \Illuminate\Broadcasting\Channel|array
         */
        public function broadcastOn()
        {
            // dd(Auth::user());
            return new PrivateChannel('user.' . $this->userId);
        }
    
    // 精细化返回的数据,如果加了这个函数,公有属性才不会返回而是以这个函数内放回的字段为主
    //    public function broadcastWith()
    //    {
    //        return [
    //            'data' => '2424',
    //        ];
    //    }
    }
    

    BroadcastServiceProvider:

    <?php
    
    namespace App\Providers;
    
    use Illuminate\Support\ServiceProvider;
    use Illuminate\Support\Facades\Broadcast;
    
    class BroadcastServiceProvider extends ServiceProvider
    {
        /**
         * Bootstrap any application services.
         *
         * @return void
         */
        public function boot()
        {
            //Broadcast::routes();
            Broadcast::routes(['middleware' => 'api']);
            #routes()参数如果不配置 默认走的是web中间件
            #'middleware' => 'api' 然后广播路由走api中间件,自己也可以定义其他类型的中间件
    
            require base_path('routes/channels.php'); #加载检查权限的广播路由
        }
    }
    
    

    routes/channels:#广播路由只针对广播的

    <?php
    
    /*
    |--------------------------------------------------------------------------
    | Broadcast Channels
    |--------------------------------------------------------------------------
    |
    | Here you may register all of the event broadcasting channels that your
    | application supports. The given channel authorization callbacks are
    | used to check if an authenticated user can listen to the channel.
    |
    */
    
    //占位符模式
    \Illuminate\Support\Facades\Broadcast::channel('user.{userId}', function ($user, $userId) {
        return true;
    }, ['guards' => ['api']]);
    
    #{userId}只是占位符
    #$user 闭包默认的第一个参数,授权的用户
    #$userId 时间模板的公有属性(此时该值为3590即在PrivateEvent构造函数上所赋的值),也可以是其他的对象
    #闭包函数接受多个参数,这个参数由事件里的broadcastOn函数声明的频道决定,如:'user.' . $this->userId . $this->userName 那么就可以接受2个参数userId和userName
    
    //显式的路由模型绑定
    \Illuminate\Support\Facades\Broadcast::channel('user.{user2}', function ($user, \App\Models\UserModel $user2) {
        \Illuminate\Support\Facades\Log::info($user);
        return true;
    }, ['guards' => ['api']]);
    # 注意这里的占位符{user2} 必须 \App\Models\UserModel $user2  这个变量名一样。否则会报错
    

    前端代码

    <script>
    import Echo from 'laravel-echo'
    
    window.io = require('socket.io-client');
    window.Echo = new Echo({
        broadcaster: 'socket.io',
        host: window.location.hostname + ':6001',
        auth: {
             headers: {
                 Authorization: 'Bearer ' + 'WVP25lQfJFTpCcuA1rmdadgeXQplMOtobWjL4TvkDD8dMbjOX5pBF4kBwiC9'
             },
         },
    });
    
    window.Echo.private('user.3590')
        .listen('PrivateEvent', (e) => { 
                alert(11);
               console.log(1111);
            console.log(e);
        });
    </script>
    
    #user.3590 监听的频道
    #PrivateEvent 监听的事件
    #Authorization 授权,后端会检测如果不对会报错403
    

    页面展示:不出意外会把公有属性全部展示出来,其他的属性不会展示

    {
    user: {…}, userId: 3590, socket: null}
    socket: null
    user: {u_id: 3590, u_username: "02125", u_job_number: "", u_warehouse_id: 1, u_department_id: 0, …}
    userId: 3590
    __proto__: Object
    }
    

    参考:
    https://xueyuanjun.com/post/19505
    http://silverd.cn/2018/06/01/laravel-broadcasting-adv.html

    相关文章

      网友评论

        本文标题:Laravel+vue公有/私有广播实战

        本文链接:https://www.haomeiwen.com/subject/nctzghtx.html