I am trying to create a real-time notification system using Laravel as the backend API Client and a SPA for my frontend, I am using React as the frontend, but for the below example I will be using a simple Vue.Js and blade that I have created in order to get a working example.
So, all in all, I have a route that fires an event, this is shown like the below example:
Route::get('fire', function () {
// this fires the event
$user = App\Models\User::find(1);
event(new App\Events\CampaignUploadedWithSuccess($user, 'testing a notification'));
return "event fired";
});
The event that it fires will look like this
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class CampaignUploadedWithSuccess implements ShouldBroadcast
{
protected $user;
public $notification;
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @param $user
* @param $notification
*/
public function __construct($user, $notification)
{
$this->user = $user;
$this->notification = $notification;
}
/**
* Get the channels the event should broadcast on.
*
* @return Channel|array
*/
public function broadcastOn()
{
return ['notifications-channel.' . $this->user->id];
}
}
So I am broadcasting on a channel called notification-channel.{userId}
I then have a socket.js file that I run using node.
That looks like this
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();
redis.subscribe('notifications-channel.1', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log('Notification Recieved: ' + message);
message = JSON.parse(message);
io.emit(channel + ':' + message.event, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
using node socket.js runs the server and firing the event does what I want like below:
Happy Days! I am broadcasting to a channel..
However, I now have a blade file called test.blade that will pull in Vue and Socket.io
That looks like this
<!DOCTYPE html>
<html>
<head>
<title>Laravel</title>
</head>
<body>
<h1>Notifications</h1>
<ul>
<li v-repeat="notification: notifications">@{{ notifications }}</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/0.12.16/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js"></script>
<script>
var socket = io('http://localhost:3000');
new Vue({
el: 'body',
data: {
notifications: []
},
ready: function() {
socket.on('notifications-channel.1', function(data) {
alert(data.notification);
});
}
});
</script>
</body>
</html>
And the goal here is to have the message alert when the notification-channel.1 has data broadcasted to it. Yet this does not work.
So my question is, how does one broadcast to a channel and consume that broadcast from the channel using socket.io, Laravel and Redis.
I am also a bit in the dark on Private Channels and how I can create a channel only for one user. The documentation is good, yet it does not provide real world examples of how to achieve this and have notifications consumed by multiple platforms.
