Laravel 事件与 socket-io [接收通知]

maf*_*tis 10 php socket.io laravel

第一次尝试用laravelsocket-io我想很简单的通知发送给管理员。到目前为止,我的事件正在触发,但我需要帮助接收事件通知

逻辑

这是非常基础的,因为我想了解这个过程。

  1. 用户打开页面 Add Product
  2. 管理员得到通知user X是在App Product页。

迄今为止

到目前为止,我可以触发事件并获取用户数据(Add Product页面中的用户)

需要帮助

我需要帮助来了解管理员接收通知的方式。

代码

组件脚本

created() {
  let user = JSON.parse(localStorage.getItem("user"))
  this.listenForBroadcast(user);
},
methods: {
  listenForBroadcast(user) {
    Echo.join('userInAddProduct')
    .here((Loggeduser) => {
      console.log('My user data', Loggeduser);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

上面代码的结果

My user data [{…}]
  0:
    id: 1
    name: "Test User"
    photo: "User-1588137335.png"
    __ob__: Observer {value: {…}, dep: Dep, vmCount: 0}
    get id: ƒ reactiveGetter()
    set id: ƒ reactiveSetter(newVal)
    get name: ƒ reactiveGetter()
    set name: ƒ reactiveSetter(newVal)
    get photo: ƒ reactiveGetter()
    set photo: ƒ reactiveSetter(newVal)
    __proto__: Object
    length: 1
    __proto__: Array(0)
Run Code Online (Sandbox Code Playgroud)

渠道路线

Broadcast::channel('userInAddProduct', function ($user) {
    return [
        'id' => $user->id,
        'photo' => $user->photo,
        'name' => $user->name
    ];
});
Run Code Online (Sandbox Code Playgroud)

MessagePushed(事件文件)

class MessagePushed implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function broadcastOn()
    {
        return new PresenceChannel('userInAddProduct');
    }
}
Run Code Online (Sandbox Code Playgroud)

如何接收有关此事件触发的通知?我想通知user x页面中的管理员用户Add Product

更新

自从我发布这个问题以来,我做了一些更改,这是我的最新代码 + 问题。

bootstrap.js

window.io = require('socket.io-client');

window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001',
    auth: { // added authentication token (because all my events are private)
        headers: {
            Authorization: localStorage.getItem('access_token'),
        },
    },
});
Run Code Online (Sandbox Code Playgroud)

Add.vue (add product component where event has to be fired)

listenForBroadcast(user) {
    let ui = JSON.parse(localStorage.getItem("user"))
    Echo.join('userInAddProduct')
    .here((users) => {
        console.log('My user data', users)
    })
    .joining((user) => {
        this.$notify({
            title: '',
            message: user + 'joining',
            offset: 100,
            type: 'success'
        });
    })
    .leaving((user) => {
        this.$notify({
            title: '',
            message: user + 'is leaving new product',
            offset: 100,
            type: 'warning'
        });
    })
    .whisper('typing', (e) => {
        this.$notify({
            title: '',
            message: ui.username + 'is adding new product',
            offset: 100,
            type: 'success'
        })
    })
    .listenForWhisper('typing', (e) => {
        console.log(e)
        this.$notify({
            title: '',
            message: ui.username + 'is entered add new product page.',
            offset: 100,
            type: 'success'
        });
    })
    .notification((notification) => {
        console.log('noitication listener: ', notification.type);
    });
},
Run Code Online (Sandbox Code Playgroud)

然后我制作了 4 个文件来处理事件:

  • 事件 ( passing data)
  • 事件监听器(process the database storageshowing notifications在线管理员)
  • 观察员(开火事件)
  • 通知(store data to database对于管理员,以防事件发生时他们不在线,以便他们以后可以看到通知)

Event file

class MessagePushed extends Event implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;
    public $product;

    public function __construct(User $user, Product $product)
    {
        $this->user = $user;
        $this->product = $product;
    }

    public function broadcastOn()
    {
        return new PresenceChannel('userInAddProduct');
    }
}
Run Code Online (Sandbox Code Playgroud)

Listener file

class ThingToDoAfterEventWasFired implements ShouldQueue
{
    public function handle(MessagePushed $event)
    {
        //Log testing purpose only
        $user = $event->user->username;
        $product = $event->product->name;

        // Real data that should be broadcasts
        $user2 = $event->user;
        $product2 = $event->product;

        // inform all admins and authorized staffs about new product
        $admins = User::role(['admin', 'staff'])->get();
        foreach($admins as $admin) {
            $admin->notify(new UserAddProduct($user2, $product2));
        }

        Log::info("Product $product was Created, by worker: $user");
    }
}
Run Code Online (Sandbox Code Playgroud)

Notification

class UserAddProduct extends Notification implements ShouldQueue
{
    use Queueable;

    protected $product;
    protected $user;

    public function __construct(User $user, Product $product)
    {
        $this->product = $product;
        $this->user = $user;
    }

    public function via($notifiable)
    {
        return ['database', 'broadcast'];
    }

    public function toDatabase($notifiable)
    {
        return [
            'user_id' => $this->user->id,
            'user_username' => $this->user->username,
            'product_id' => $this->product->id,
            'product_name' => $this->product->name,
        ];
    }

    public function toArray($notifiable)
    {
        return [
            'id' => $this->id,
            'read_at' => null,
            'data' => [
                'user_id' => $this->user->id,
                'user_username' => $this->user->username,
                'product_id' => $this->product->id,
                'product_name' => $this->product->name,
            ],
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

Observer

public function created(Product $product)
{
    $user = Auth::user();
    event(new MessagePushed($user, $product));
}
Run Code Online (Sandbox Code Playgroud)

问题

  1. 在整个应用程序中触发事件后,如何立即返回实时通知?目前我的代码被放置在add.vue component admins get notify IF they are in same page only :/
  2. 如何获得多个事件的通知?让说我有另一event, listener, observer对我要管理通知双方的其他页面操作product event,并other event在整个应用程序。

谢谢

maf*_*tis 1

解决了

这是我根据我的需要和问题完成的方法(如果您的情况与我的情况不同,可能会有所不同)

在组件中发生活动(在我的例子中Add.vue

Echo.join('userInAddProduct')
.here((users) => {
    console.log('here: ', users);
})
.joining((user) => {
    console.log('joining: ', user);
})
.leaving((user) => {
    console.log('leaving: ', user);
})
.whisper('typing', {data: notf}) // this part sends my data
.notification((notification) => {
    console.log('noitication listener1: ', notification.type);
});
Run Code Online (Sandbox Code Playgroud)

由于我需要我的通知在所有页面中对管理员可见,因此我已将套接字发射(即Echo.listenForWhisper)添加到我的导航栏组件中。

mounted() {
  this.notifs();
    window.Echo.join('userInAddProduct')
       // listen to broadcast from Add.vue
      .listenForWhisper('typing', (product) => {
        // add it into my navbar notifications list
        this.notifications.unshift(product);
      });
}
Run Code Online (Sandbox Code Playgroud)

现在,每次用户向服务器管理员添加新产品时都会收到通知。

注意要查看此功能的其他设置,请滚动回我的更新部分并查看Event, Listener & Observe文件代码。(您将这些文件和上面的所有代码制作为您首选的组件,然后您将收到实时通知)。