Laravel broadcast not alerting the message on the frontend - laravel

I am quite new to this laravel event so I am quite unable to get it done correctly.
I am trying to fire an event to notify the user when the job is completed. So, I am triggering an event at the end of the job as
event(new AmenityUploaded($this->data['property_id']));
My event looks like:
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 AmenityUploaded implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $property_id;
public function __construct($property_id)
{
$this->property_id = $property_id;
}
public function broadcastOn()
{
return new PrivateChannel('channel.amenity.'.$this->property_id);
}
public function broadcastAs()
{
return 'amenity-uploaded';
}
}
And in routes/channel.php
Broadcast::channel('channel.amenity.{propertyId}', function ($user, $propertyId) {
// return $user->id === \App\Models\Property::find($propertyId)->updated_by;
return true;
}
And in view, I am using javascript as:
view
<script>
Pusher.logToConsole = true;
var pusher = new Pusher('xxxxxxxxxxxxxxxxxxxxx', {
cluster: 'us3',
forceTLS: true
});
$id = '<?php echo $r->id; ?>';
var channel = pusher.subscribe(`channel.amenity.${$id}`);
channel.bind('amenity-uploaded', function(data) {
alert(JSON.stringify(data));
});
</script>
And my .env looks like:
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=xxxxx
PUSHER_APP_KEY=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_SECRET=xxxxxxxxxxxxxxxxxxxx
PUSHER_APP_CLUSTER=us3
So, whenever I run the queue with php artisan queue:work --tries=3. In the end, I could see that App\Events\AmenityUploaded being fired. However, I could not see any alert on the front end.
However, If I try to push notifications from the pusher dashboard, it alerts successfully on the app successfully. While pushing from pusher debug console, I use the channel as channel.amenity.1 and event as amenity-uploaded
##Update
I have added a block in event as broadcastWith:
public function broadcastWith()
{
// This must always be an array. Since it will be parsed with json_encode()
return [
'name' => 'Saroj',
'message' => 'Message',
];
}
And, this is successfully showing in pusher dashboard. However, not alerting in the frontend yet.
update 2
Tried with echo: Added following code in bootstrap.js
import Echo from 'laravel-echo'
import Pusher from "pusher-js"
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'xxxxxxxxxxxxxxxxxxxx',
cluster: 'us3',
encrypted: true
});
And in view:
<script>
$id = '<?php echo $r->id; ?>';
Echo.channel(`channel.amenity.${$id}`)
.listen('.amenity-uploaded', (data) => {
alert(JSON.stringify(data));
});
</script>
Still the same, if fired from the pusher dashboard, an alert will be shown in frontend. After finishing jobs, the event can be seen at the pusher dashboard, however not on the frontend.

I think the issue is that you use only Pusher at frontend without laravel-echo which should be required to work with private channels. Pusher itself doesn't know that it must authorise, laravel-echo does that out of the box.
This is how I init Pusher and Echo:
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: fromPHP.PUSHER_APP_KEY,
cluster: fromPHP.PUSHER_CLUSTER,
encrypted: true
});
and this is how I listen for private events:
Echo.private(channel).listen('.amenity-uploaded', data => alert(JSON.stringify(data)));
Notice the leading . before amenity-uploaded. That's required when you customise broadcastAs (https://laravel.com/docs/5.8/broadcasting#broadcast-name)

Related

How to automatically update data in laravel view?

I have a view which will show the list important tasks from database. I have a function in controller which returns the collection of data to the view.
My controller function is
public function list()
{
$tasks= Task::where('category','1')->get();
//category is 1 when the task is important
return view('important', compact('tasks'));
}
My view is like
<ul>
#foreach ($tasks as $task)
<li> {{$task->body}}</li>
#endforeach
</ul>
What I want to essentially do is to call the list function whenever a new important task is added into the database. How can I do that?
in your web.php
Route::get('/tasks','TasksController#list')->name('get_tasks');
inside your controller :
use Illuminate\Http\Request;
public function list(Request $request)
{
$tasks= Task::where('category','1')->get();
if($request->ajax()){
return response()->json(array('tasks'=>$tasks));
}
return view('important', compact('tasks'));
}
inside your blade view :
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
$(document).ready(function(){
setInterval(function(){
$.ajax({
url:'/tasks',
type:'GET',
dataType:'json',
success:function(response){
if(response.tasks.length>0){
var tasks ='';
for(var i=0;i<response.tasks.length;i++){
tasks=tasks+'<li>'+response.tasks[i]['body']+'</li>';
}
$('#tasklist').empty();
$('#tasklist').append(tasks);
}
},error:function(err){
}
})
}, 5000);
});
</script>
<ul id="tasklist">
#foreach ($tasks as $task)
<li> {{$task->body}}</li>
#endforeach
</ul>
To achieve this kind of setup you may use Pusher or any other similar provider, once you signup on pusher you can send 200k notifications per day for free, you can check the limits after login to pusher. Before we proceed please install pusher's official php package
composer require pusher/pusher-php-server
From your pusher dashboard obtain app_id, key, secret and cluster now in your controller/model where you are inserting the data in database add the following code
//You will get cluster name from pusher.com replace it below
$options = ['cluster' => 'mt1', 'encrypted' => true];
//Replace your key, app_id and secret in the following lines
$pusher = new Pusher(
'key',
'secret',
'app_id',
$options
);
//this could be a single line of message or a json encoded array, in your case you want to pass some data to display in table I assume you have an array
$message= json_encode(['name' => 'John doe', 'age' => 42, 'etc' => 'etc']);
//Send a message to users channel with an event name of users-list. Please mind this channel name and event name could be anything but it should match that with your view
$pusher->trigger('users', 'users-list', $message);
Now in your view before the </body> tag paste the following code
<!-- Incldue Pusher Js -->
<script src="https://js.pusher.com/4.2/pusher.min.js"></script>
<script>
//Remember to replace key and cluster with the credentials that you have got from pusher.
var pusher = new Pusher('key', {
cluster: 'mt1',
encrypted: true
});
//In case you have decided to use a different channel and event name in your controller then change it here to match with the one that you have used
var channel = pusher.subscribe('users');
channel.bind('users-list', function(message) {
//if you will console.log(message) at this point you will see the data
//that was sent from your controller is available here please consume as you may like
alert(message);
});
</script>

Could not be authenticated to private-App - Laravel Notification, Laravel Echo, Socket

I'm using Laravel Echo Server with Socket.io. Also I want to use Laravel Notifications for the Real Time Notifications.
Below is my bootstrap.js
import Echo from 'laravel-echo'
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':7878'
});
Below is my routes/channels.php
Broadcast::channel('App.Domain.User.User.{id}', function ($user, $id) {
return true;
});
And following is the code in my blade file:
<script>
Echo.private('App.Domain.User.User.' + '{{ auth()->user()->id }}')
.notification((notification) => {
console.log('yes');
console.log(notification.type);
$.notify('success', {type: 'success'});
});
</script>
But I'm getting the following error:
What could be the reason?
Thanks to all in advance.

Private Channel not working in Laravel

In my ChatEvent i called function
public function broadcastOn()
{
return new Channel('chat');
}
And in app.js i have Echo.
Echo.channel('chat')
.listen('ChatEvent', (e) => {
this.chat.message.push(e.message);
console.log(e);
})
It works pretty well. But, when i change Channel to PrivateChannel in function broadcastOn() and in app.js I change
Echo.private('chat')
.listen('ChatEvent', (e) => {
this.chat.message.push(e.message);
console.log(e);
})
I have error POST broadcasting/auth 403 (Forbidden) ## And
Can I use Channel instead of PrivateChannel?
Like mentioned in document you have to define the authorization rule for this private channel
https://laravel.com/docs/5.5/broadcasting#authorizing-channels
edit your routes/channels.php file
Broadcast::channel('chat', function ($user) {
return true; //for public access
// or
return $user->can('chat'); //using gate
});
else use the channel for public access
When you use Private or PresenceChannel, Fix Error 403 /broadcasting/auth with Laravel version > 5.3 & Pusher, you need change your code in resources/assets/js/bootstrap.js with
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your key',
cluster: 'your cluster',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + YourTokenLogin
},
},
});
And in app/Providers/BroadcastServiceProvider.php change by
Broadcast::routes()
with
Broadcast::routes(['middleware' => ['auth:api']]);
or
Broadcast::routes(['middleware' => ['jwt.auth']]); //if you use JWT
it worked for me, and hope it help you.
Try this
in Chat event add
public function broadcastAs()
{
return 'new.chat';
}
in your javascript file
Echo.channel('chat')
.listen('.new.chat', (e) => {
console.log(e);
})
if use api
window.Echo.connector.options.auth.headers['Authorization'] = `Bearer ${user.api_token}`;
if use session auth without top code

Laravel echo admin channel authentication error

I'am using Laravel 5.5 with echo for an admin panel ,
the main guard (web) is related to Admin class ,
the private channel name that i want to get is Admin.1 ,
The problem is when i change the channel name from
Echo.private('App.User.' + this.userid)
to
Echo.private('App.Admin.' + this.userid)
it gets me this error
broadcasting/auth 500 (Internal Server Error)
what i tried is :
i put this
Broadcast::routes(['middleware' => [ 'api', 'web','auth' ] ]);
in web.php and api.php and BroadcastServiceProvider.php put it doesn't seem to work
i also tried this soltion
How to define or pass auth guard for broadcast authentication routes instead of default auth guard?
In your echo settings set authEndpoint to 'broadcasting/auth'.
here's the code that works for me after facing the same problem.
new Echo({
broadcaster: 'pusher',
key: '{{env("PUSHER_APP_KEY")}}',
cluster: 'us2',
encrypted: true,
authEndpoint: '{!! env("APP_URL") !!}/broadcasting/auth',
});
I solve my problem by :
adding this to BroadcastServiceProvider
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
/*
* for auth user channel
*/
Broadcast::channel('App.Admin.{id}',function($user, $id){
return (int) $user->id === (int) $id;
});
}

POST http://localhost:8000/broadcasting/auth 403 (Forbidden)

I am trying to make my app connecting to pusher on a private channel.
But I am getting the following error in console:
POST http://localhost:8000/broadcasting/auth 403 (Forbidden)
app.js
/**
* First we will load all of this project's JavaScript dependencies which
* includes Vue and other libraries. It is a great starting point when
* building robust, powerful web applications using Vue and Laravel.
*/
require('./bootstrap');
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('payment', require('./components/Payment.vue'));
Vue.component('form-ajax', require('./components/FormAjax.vue'));
Vue.component(
'passport-clients',
require('./components/passport/Clients.vue')
);
Vue.component(
'passport-authorized-clients',
require('./components/passport/AuthorizedClients.vue')
);
Vue.component(
'passport-personal-access-tokens',
require('./components/passport/PersonalAccessTokens.vue')
);
const app = new Vue({
el: '#app'
});
Echo.private(`articles.admin`)
.listen('ArticleEvent', function(e) {
console.log(e);
});
Error
What maybe the cause of the error and how to resolve it.
Error 403 /broadcasting/auth with Laravel version > 5.3 & Pusher, you need change your code in resources/assets/js/bootstrap.js with
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your key',
cluster: 'your cluster',
encrypted: true,
auth: {
headers: {
Authorization: 'Bearer ' + YourTokenLogin
},
},
});
And in app/Providers/BroadcastServiceProvider.php change by
Broadcast::routes()
with
Broadcast::routes(['middleware' => ['auth:api']]);
or
Broadcast::routes(['middleware' => ['jwt.auth']]); //if you use JWT
it worked for me, and hope it help you.
Have you tried to customise your authEndpoint.
this thing works on my end.
bootsrap.js
window.Echo = new Echo({
broadcaster: 'pusher',
// ...
authEndpoint: '/custom/endpoint/auth'
});
In my case I have used a custom auth guard which is causing the problem.
I have added the middleware to pass my custom auth guard and this solves the problem.
public function boot()
{
Broadcast::routes(['middleware' => 'auth:admin']);
require base_path('routes/channels.php');
}
This link explains more what's going on.
I added below code to routes/web.php and it worked.
Route::post('/broadcasting/auth', function () {
return Auth::user();
});
I Have faced same problem and this trick save my life.
go to api.php
Broadcast::routes(['predix' => 'api', 'middleware' => ['auth:api']]);

Resources