I know broadcast is for others to get the message in real-time. But for some reason I need it to be received only by sender. How to achieve this? Right now, the broadcast is received by all excerpt for the sender.
I'm using redis+ socket.io + laravel event + laravel queue
I did try something like passing the logged in user id in the broadcast message from server side and then from client side check if the login id match with the one coming from server. Then only reveal the message. But it seems like, somewhere is configured that sender wont get the message. It's only subscribed by other users connected to the socket.
So how can I control it from server side? How can I make the sender subscribe to this particular channel?
DashboardEvent file:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class DashboardEvent implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $actionId;
public $actionData;
public $user;
/**
* Create a new event instance.
*
* #author Author
*
* #return void
*/
public function __construct($actionId, $actionData, $user)
{
$this->actionId = $actionId;
$this->actionData = $actionData;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #author Author
*
* #return Channel|array
*/
public function broadcastOn()
{
// return new Channel('action-channel-one');
return [new Channel('action-channel-one')];
}
/**
* Get the data to broadcast.
*
* #author Author
*
* #return array
*/
public function broadcastWith()
{
return [
'actionId' => $this->actionId,
'actionData' => $this->actionData,
'sender'=>$this->user
];
}
}
socket.js file
'use strict';
var cors = require('cors');
var app = require('express')();
app.use(cors({origin: '*'}));
var server = require('http').Server(app);
var io = require('socket.io')(server);
require('dotenv').config();
io.on('connection', function(socket) {
console.log('connected'+socket.id);
});
var redisPort = process.env.REDIS_PORT;
var redisHost = process.env.REDIS_HOST;
var ioRedis = require('ioredis');
var redis = new ioRedis(redisPort, redisHost);
redis.subscribe('test_database_action-channel-one');
redis.on('message', function (channel, message) {
message = JSON.parse(message);
console.log(message);
io.emit(channel + ':' + message.event, message.data);
});
var broadcastPort = process.env.BROADCAST_PORT;
server.listen(broadcastPort, function () {
console.log('Socket server is running.');
});
client side
var sock = io("http://127.0.0.1:3444", {
transports: ['websocket']
});
var sender = "{{ auth()->check() ? Auth::id() : 'false' }}";
sock.on('test_database_action-channel-one:App\\Events\\DashboardEvent', function (data) {
console.log(data);
var action = data.actionId;
var actionData = data.actionData;
var user = data.sender;
//if sender
if (user == sender) {
console.log('this is the sender');
}
});
Related
I am trying to use Pusher Notificaiton system to use web sockets to update the current page with the message "YOu have a new Notification" and the bell icon indicating the number of unread notifications. I registered the Events and Listeners and have implemented ShouldBroadcase and connected everything. But I am not getting any message. And unless the page reloads, I am not getting the no. of unread notifications as well.
Here are my codes
Event
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewNotificationEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
protected $data;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($data)
{
$data = $this->data;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return ['my-channel'];
}
public function broadcastAs()
{
return 'my-event';
}
}
Listener
<?php
namespace App\Listeners;
use App\Events\NewNotificationEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use DB;
use Illuminate\Support\Facades\Auth;
class NewNotificationListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param NewNotificationEvent $event
* #return void
*/
public function handle(NewNotificationEvent $event)
{
$users = Auth::user();
DB::select('CALL notification_tbl(?)',array($users->id));
}
}
Controller
if(Gate::allows('manage-users')){
$userid = $request->userid;
$notf = $request->notf;
$priority = $request->priority;
DB::table('notifications')->insert(['user_id'=>$userid,'notf_message'=>$notf,'priority'=>$priority]);
$data = array(
'userid'=>$userid,
'priority'=>$priority,
'notf_message'=>$notf,
);
event (new NewNotificationEvent($data));
// DB::select('CALL notification_tbl(?)',array($userid));
return response()->json([
'success'=>true,
'msg'=>"User Notified",
]);
}
abort(403, "This Page is only available for Admin");
}
}
Notification sent from Backend (Backend Controller)
public function sendNotf(Request $request){
if(Gate::allows('manage-users')){
$userid = $request->userid;
$notf = $request->notf;
$priority = $request->priority;
DB::table('notifications')->insert(['user_id'=>$userid,'notf_message'=>$notf,'priority'=>$priority]);
DB::select('CALL notification_tbl(?)',array($userid));
$data = array(
'userid'=>$userid,
'priority'=>$priority,
'notf_message'=>$notf,
);
// event (new NewNotificationEvent($data));
return response()->json([
'success'=>true,
'msg'=>"User Notified",
]);
}
abort(403, "This Page is only available for Admin");
}
JS Code (Available in the common blade page- the one which includes the Navbar and is included in every other page)
<script src="https://js.pusher.com/7.0/pusher.min.js"></script>
<script>
// Enable pusher logging - don't include this in production
Pusher.logToConsole = true;
var pusher = new Pusher('be850f6784915a1d43b8', {
cluster: 'ap2'
});
var channel = pusher.subscribe('user-channel');
channel.bind('user-channel', function(data) {
alert(JSON.stringify(data));
});
</script>
First of all, make your notification by php artisan make:notification exNotification
then implement your notification in toBroadcast function
return (new BroadcastMessage([
//
]))
Finally use
$user->notify(new exNotification());
Also, you can define your channel name in receivesBroadcastNotificationsOn in User Model
public function receivesBroadcastNotificationsOn()
{
return 'user.'.$this->id;
}
for more detail please visit :
Notifications
composer require pusher/pusher-php-server
PUSHER_APP_ID=322700
BROADCAST_DRIVER=pusher
// Get the credentials from your pusher dashboard
PUSHER_APP_ID=XXXXX
PUSHER_APP_KEY=XXXXXXX
PUSHER_APP_SECRET=XXXXXXX
//header or footer file
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="//js.pusher.com/3.1/pusher.min.js"></script>
<script type="text/javascript">
var pusher = new Pusher('API_KEY_HERE', {
encrypted: true
});
// Subscribe to the channel we specified in our Laravel Event
var channel = pusher.subscribe('my-channel');
channel.bind('App\\Events\\NewNotificationEvent', function(data) {
console.log('New event');
//reload page for append data to any div
});
</script>
I have the following code:
/routes/web.php
<?php
use App\Events\UserSignedUp;
Route::get('/', function () {
$data = [
'event' => 'UserSignedUp',
'data' => [
'username' => 'JohnDoe'
]
];
//Redis::publish('test-channel', json_encode($data));
event(new UserSignedUp('JohnDoe'));
return view('welcome');
});
where I'm using the function: event(...).
I also have the following Event file:
/app/Events/UserSignedUp.php
<?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 UserSignedUp implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $username;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($username)
{
$this->$username = $username;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('test-channel');
}
}
Then, I'm listening the event on a Node.js file:
/socket.js
var server = require('http').Server();
var io = require('socket.io')(server);
var Redis = require('ioredis');
var port = process.env.PORT || 3000;
var redis = new Redis();
redis.subscribe('test-channel');
redis.on('message', function(channel, message) {
console.log(channel, message);
});
server.listen(port, function(){
console.log('listening on *:' + port);
});
My problem is that when on the file above: /routes/web.php I use:
event(new UserSignedUp('JohnDoe'));
the event doesn't arrive to the Node.js listener. However, the event is arriving properly to Redis because I can see it with: $ redis-cli monitor command.
[EDIT 1] The following is what I get when the event(...) function is called:
1541489387.307573 [0 127.0.0.1:52109] "SELECT" "0"
1541489387.308379 [0 127.0.0.1:52109] "RPUSH" "queues:default" "{\"displayName\":\"App\\\\Events\\\\UserSignedUp\",\"job\":\"Illuminate\\\\Queue\\\\CallQueuedHandler#call\",\"maxTries\":null,\"timeout\":null,\"timeoutAt\":null,\"data\":{\"commandName\":\"Illuminate\\\\Broadcasting\\\\BroadcastEvent\",\"command\":\"O:38:\\\"Illuminate\\\\Broadcasting\\\\BroadcastEvent\\\":7:{s:5:\\\"event\\\";O:23:\\\"App\\\\Events\\\\UserSignedUp\\\":2:{s:8:\\\"username\\\";N;s:6:\\\"socket\\\";N;}s:10:\\\"connection\\\";N;s:5:\\\"queue\\\";N;s:15:\\\"chainConnection\\\";N;s:10:\\\"chainQueue\\\";N;s:5:\\\"delay\\\";N;s:7:\\\"chained\\\";a:0:{}}\"},\"id\":\"7CjGqwcRXoZhVIJyFU8AcQ5aTW8G6Cke\",\"attempts\":0}"
In the other hand, when I use:
Redis::publish('test-channel', json_encode($data));
The event arrives properly to the Node.js listener.
[EDIT 2] The following is what I get when the Redis::publish(...) function is called:
1541489590.930114 [0 127.0.0.1:52124] "SELECT" "0"
1541489590.930872 [0 127.0.0.1:52124] "PUBLISH" "test-channel" "{\"event\":\"UserSignedUp\",\"data\":{\"username\":\"JohnDoe\"}}"
Any idea about why the event is not arriving to the Node.js listener event though is arriving to the Redis server first?
Thanks.
I've already installed node.js , socket.io, predis,ioredis in laravel 5.2
When i run
node socket.js
in gitbash ,nothing is returned.
at localhost:3000, first it loads for sometime then localhost didn't send any data error is displayed.(done should be displayed)
socket.js file: http://laravel.io/bin/OeGxv
routes file: http://laravel.io/bin/d9PvY
package.json: http://laravel.io/bin/Kk5mB
I dont think can help you, but I successfull using redis with Laravel 5.1 and this is code.
composer.json
"require": {
"php": ">=5.5.9",
"laravel/framework": "5.1.*",
"pusher/pusher-php-server": "^2.2",
"predis/predis": "^1.1"
routes.php
Route::get('/setredis',[
'as'=>'set.redis',
'uses'=>'TestController#index'
]);
Route::get('/getredis',[
'as'=>'get.redis',
'uses'=>'TestController#create'
]);
Route::get('fire', function () {
// this fires the event
event(new \App\Events\EventName());
return "event fired";
});
Route::get('test', function () {
// this checks for the event
return view('test');
});
TestController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use Redis;
class TestController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
Redis::set('name', 'Taylor');
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
$user = Redis::get('name');
echo $user;
}
test.blade.php
#extends('master')
#section('content')
<p id="power">0</p>
#stop
#section('footer')
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script>
var socket = io('http://testlaravel5.com:3000');
socket.on("test-channel", function(message){
console.log(message);
// increase the power everytime we load test route
$('#power').text(parseInt($('#power').text()) + parseInt(message.data.power));
});
</script>
#stop
socket.js
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('test-channel', function(err, count) {
});
redis.on('message', function(channel, message) {
console.log('Message Recieved: ' + message);
message = JSON.parse(message);
io.emit(channel, message.data);
});
http.listen(3000, function(){
console.log('Listening on Port 3000');
});
EventName.php
<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class EventName extends Event implements ShouldBroadcast
{
use SerializesModels;
public $data;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
$this->data = array(
'power'=> '10'
);
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return ['test-channel'];
}
}
I hope help you!
I was broadcasting my event with help of pusher,it's worked fine but when i used queue implementation then pusher haven't receive any broadcast or may be event is not broadcasting.I'm not understand what the issue is.Code is given below please help me
Controller function
public function index()
{ $this->user_id=2;
Event::fire(new UpdateDeviceStatus($this->user_id));
}
Event file
class UpdateDeviceStatus extends Event implements ShouldBroadcast
{
use SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $devices;
public function __construct($id)
{
$this->devices=Device::with('units')->where('user_id',$id)->get();
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return ['update-status'];
}
}
js file
Pusher.logToConsole = true;
var pusher = new Pusher('key', {
encrypted: true
});
var channel = pusher.subscribe('update-status');
channel.bind('App\\Events\\UpdateDeviceStatus', function (data) {
console.log(data);
});
I had the same issue and realised that I just forgot to listen to the queue: php artisan queue:listen redis
I have the following event:
<?php
namespace SixtyFiveContrib\Events;
use Auth;
use SixtyFiveContrib\Events\Event;
use SixtyFiveContrib\Models\Notification;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
/**
* NotificationEvent
*
*/
class NotificationEvent extends Event implements ShouldBroadcast
{
use SerializesModels;
public $notification;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Notification $notification)
{
$this->notification = $notification;
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return ['feed', 'updates'];
}
public function broadcastWith()
{
return ['notification' => $this->notification];
}
}
I'm using the Redis driver in broadcasting.php
'redis' => [
'driver' => 'redis',
'connection' => 'default',
],
Then I have the node app from the official docs, which runs fine and connects to the client:
var app = require('http').createServer(handler);
var io = require('socket.io')(app);
var Redis = require('ioredis');
var redis = new Redis();
app.listen(3000, function() {
console.log('Server is running!');
});
function handler(req, res) {
res.writeHead(200);
res.end('Ayup.');
}
io.on('connection', function(socket) {
//
});
redis.psubscribe('*', function(err, count) {
console.log(err);
});
redis.on('pmessage', function(subscribed, channel, message) {
message = JSON.parse(message);
console.log(subscribed);
console.log(channel);
console.log(message);
io.emit(channel + ':' + message.event, message.data);
});
The node app isn't receiving anything from Redis? If I manually go into redis-cli and run ``` PUBLISH feed '{event: "SixtyFiveContrib\Events\NotificationEvent"}' then the node app does receive that message.
Cheers in advance!
Had this problem myself just now.
Apparently, broadcasted events use the QUEUE_DRIVER:
See "Queue Prerequisites":
Before broadcasting events, you will also need to configure and run a queue listener. All event broadcasting is done via queued jobs so that the response time of your application is not seriously affected.
So, to catch the events immediately, you could set QUEUE_DRIVER=sync.
But this is of course not advised, since all your other jobs would run in sync as well.
So it's better to set up a proper queue handler first.