Laravel function "event" not working when broadcasting an event - laravel

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.

Related

Unable to broadcast Notification in Laravel

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>

Laravel does not check the authorization when attempting to subscribe a private channel

I have newly started working with laravel broadcasting and faced a problem. I am using Pusher and I want to check if users are authorized to subscribe to a private channel. Users' access to posts' comment notification is authenticated but not authorized. I am trying to send notification of new comment only to the post's author but all authenticated users who have opened the post get notifications. Am I missing something or what?
<?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 NewCommentEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $comment;
public function __construct($comment)
{
$this->comment = $comment;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('post-'.$this->comment->post_id);
}
public function broadcastAs()
{
return 'new-comment-event';
}
public function broadcastWith()
{
return ['comment' => $this->comment->comment];
}
}
routes/channel.php:
<?php
use App\models\Post;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('post-{id}', function ($user, $id) {
return false;
//return $user->id == Post::find($id)->author_id;
});
And the JavaScript in view:
var pusher = new Pusher('904d58ankty8c8397d000', {
authEndpoint: 'http://localhost/blog/public/broadcasting/auth',
cluster: 'ap2',
forceTLS: true,
auth: {
headers: {
'X-CSRF-Token': "{{csrf_token()}}"
}
}
});
var privateChannel = pusher.subscribe("private-post-{{{$post->id}}}");
privateChannel.bind('new-comment-event', function(data) {
$('#post-comments').append('<p>'+data.comment+'</p>');
});
By the way the following is the provider code:
public function boot()
{
Broadcast::routes(['middleware' => ['auth']]);
require base_path('routes/channels.php');
}
The laravel version i am using is: 5.8
What does "$this->comment->post_id" denote? If it denotes the id of that particular post, then who ever has access to that post will get the notification. Get author_id from post_id and Broadcast on 'post-'.author_id.

Laravel Socket.I.O vuejs

hi i am trying to connect with Socket.I.O vuejs laravel
in my App.js or Main.js code is
import io from 'socket.io-client';
import Echo from 'laravel-echo';
import VueEcho from 'vue-echo';
import VueSocketio from 'vue-socket.io';
window.io = require('socket.io-client');
const EchoInstance = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
Vue.use(VueEcho, EchoInstance);
In Channels.php
Broadcast::channel('test-event', function() {
return true;
});
Example event
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 ExampleEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
return "Hello";
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('test-event');
}
public function broadcastWith()
{
return [
'data' => 'key'
];
}
}
in Routes web.php
Route::get('test-broadcast', function(){
broadcast(new \App\Events\ExampleEvent);
});
in my Components file
mounted() {
this.$echo.channel("test-event").listen("ExampleEvent", e => {
console.log(e);
});
}
according to
https://medium.com/#dennissmink/laravel-echo-server-how-to-24d5778ece8b
when i run
/test-broadcast
it have to give response in my about.vue browser console , but there is nothing to display at all. can any help what thing i am missing yet , Thanks in Advance
have you setup any queue driver? you will need to configure and run a queue listener. All event broadcasting is done via queued jobs.
or else you can use ShouldBroadcastNow interface.
change in you Example Event:
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
class ExampleEvent implements ShouldBroadcastNow
{ ...

localhost didn't send any data in laravel 5.2(socket.io )

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!

Redis not picking up Broadcast events in Laravel 5.1

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.

Resources