I've setup a notification system with Pusher and Echo on my Laravel 8 app. It works fine, I'm able to retrieve the notification event in VanillaJS with
window.Echo.private('App.Models.User.' + User.id)
.notification((notification) => {
if (notification.type === 'App\\Notifications\\JobLiked') {
let count = document.getElementById('count');
let number = count.innerHTML;
number++;
count.innerHTML = number;
}
});
But now I want to use Livewire listeners to trigger my function, then I setup :
public function getListeners()
{
return [
"echo-private:App.Models.User.{$this->authId},NotificationSent" => 'notifyNewJobLiked',
];
}
But nothing seems to work and I have no error message.. do you have any clue what could possibly going on ?
Thank you very much ! :)
Try to configure your listener with the following specific event name:
public function getListeners()
{
return [
"echo-private:App.Models.User.{$this->authId},.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated" => 'notifyNewJobLiked',
];
}
Since you are using Laravel Notifications to trigger the broadcast instead of a broadcastable event, the event name when fired defaults to Illuminate\\Notifications\\Events\\BroadcastNotificationCreated.
In Echo there are two methods to listen for incoming messages: notification and listen. The reason why it works with your vanilla js is that you are using the notification method, whereas the livewire event listener only works with Echo's listen, which expects the name of the calling event.
If you are using pusher, you can see the name of the calling event in the pusher debug console.
Also take care and add a dot in front of the namespaced event as described in the documentation.
Right way to get Echo notification in livewire:
public function getListeners()
{
$user_id = auth()->user()->id;
return [
"echo-notification:App.Models.User.{$user_id}, notification" => 'gotNotification'
];
}
As you can see the channel type is notification, not private:
echo-notification
Also don't forget to have a record authenticating the users in your channels route, same as you do for a private channel:
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Another thing I learned is that you can get the notification channel data from the returned field.
So you can do:
public function gotNotification($notification)
{
}
Related
SO i am trying to listen to event that create channel dynamically with the the ids of the two users involved. I ma using pusher and echo for this purpose
the event successfully fired from my controller and is being recorded but echo does not listens to that event.
I am using guards as the conversation will be between two admins
My channel.php code is
Broadcast::channel('chatchannel.{reciever_id}.{sender_id}', function ($user, $reciever_id, $sender_id) {
if((int) auth()->guard('admin')->user()->id === (int) $reciever_id || (int) auth()->guard('admin')->user()->id === (int) $sender_id){
return true;
}else{
return false;
}
});
app.js file looks like this
Echo.private('chatchannel.'+app_sender_id+'.'+app_reciever_id)
.listen('.chatEvent', (e) => {
console.log('subscribed');
});
I did this change in my broadcastingerviceprovider.php file according to online soultions but it did not work
Broadcast::routes(['middleware' => 'auth:admin']);
I looked for all the solutions online but could not find anything that is of actual help. Can anyone guide me on how to get it working.
Your broadcast channel is chatchannel.{reciever_id}.{sender_id}.
However your client channel is chatchannel.'+app_sender_id+'.'+app_reciever_id
This means, for a sender of A and receiver of 2 you would have the following channels:
Broadcast - chatchannel.2.A
Client - private-chatchannel.A.2.
Channel names must match for the client to receive the broadcast event. You should ensure the sender and receiver Id are in the same order on both systems and that you are using private channels in both scenarios.
I stuck very bad . in real-time laravel(version 9) project using pusher for websocket.
backend can get message but problem is Echo does not received message which sent from backend ...
Event :
class MessageSent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message ;
public function __construct($message){
$this->message=$message;
}
public function broadcastOn()
{
\Log::debug("{$this->message}");
return new Channel('chat');
}
public function broadcatAs(){
return 'chat';
}
}
JS :
Echo.channel('.chat').listen('MessageSent', (e) => {
alert(e.message)
});
further information :
1- according to Event I can log message to laravel.log file which means message sent from frontend to backend .
2-there is no error in console area
3-see debug console of pusher official site
There are 3 issues I believe. The first is you should not need to do .chat in your channel function on the frontend. The second is you mispelled broadcastAs function as broadcatAs customizes the event that is being listened for in the frontend. However, because it is mispelled you are referring to the event correctly though if you update it you will then need to change your listener to .chat . The last issue is you may not have started your queue. You need to run a daemon to handle that.
Echo.channel('chat').listen('MessageSent', (e) => {
alert(e.message)
});
however, if you update your broadcastAs spelling correctly it will need to be
Echo.channel('chat').listen('chat', (e) => {
alert(e.message)
});
I ask this question while I have done researches to find clear solution for this problem but many of available answers are just how to use Laravel Scheduler itself!
So I am creating a simple website with Laravel to let users create reminders for themselves.Users can receive reminder either on their Emails or if they are logged in, they receive a notification alert something like Facebook Notifications.
I am not sure if I am following the right path or not but I'm using Laravel Scheduler to send reminders to each specific user.
I also use Events in the Laravel to push recent changes every 1 minute to users but my problem is, all users receive same notification. For example if I want to remind an appointment to Mr X, Ms Y also receives same exact notification!!!
At this point, I have two questions:
1 - Is using Laravel Scheduler a good idea for this project or not? If not then what technology or method is recommended?
2 - If I have to use Laravel Scheduler for this project, so how can I send notification to related user? (I cannot use User ID as Laravel Scheduler is running by server itself and not users!)
I also attached my codes to show you what I have up to this point and I know the method I used in Laravel Channels Broadcast is somehow wrong but I just tried it!If anyone knows the answer please help me. Thank you
Laravel Scheduler - Command - Handle Function
public function handle()
{
$reminders = Note::whereTime('task_date', '<=', Carbon::now()->addMinutes(30))
->WhereTime('task_date', '>', Carbon::now()->subMinutes(30))->get();
foreach ($reminders as $reminder) {
if (!$reminder->notified) {
Note::find($reminder->id)
->update(['notified' => 1]);
event(new RemindUsers($reminder));
dd($reminder->title);
}
}
}
Laravel Event
public $reminder;
public function __construct($reminder)
{
$this->reminder = $reminder;
}
public function broadcastOn()
{
return new PrivateChannel('remind.'.$this->reminder->user_id);
}
public function broadcastWith () {
return [
'reminders' => $this->reminder
];
}
Laravel Channels
Broadcast::channel('remind.{id}', function ($user, $id) {
$notes = Note::where('user_id', $id)->get();
foreach ($notes as $note) {
return $user->id === $note->user_id;
}
});
Vue JS Code - Echo Method
data () {
return {
user: 1
}
},
CatchReminders () {
Echo.private(`remind.${this.user}`)
.listen('RemindUsers', (response) => {
this.$toast.info(`${response.reminders.title}`)
})
}
I am trying to fake event
public function should_assign_order()
{
Event::fake([OrderWasAssigned::class]);
.
.
.
}
and I got this error
Call to undefined method Illuminate\Support\Testing\Fakes\EventFake::getListeners()
Edit:
I tried to disable telescope as this issue
by putenv('TELESCOPE_ENABLED=false');
and same issue
I need fake only this event
I am on laravel 6
PHPUnit 9.5.4.
If I understand correctly, then you are looking for scoped events as you want to test a specific event
/**
* Test order process.
*/
public function test_orders_can_be_processed()
{
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// Events are dispatched as normal and observers will run ...
$order->update([...]);
}
}
You can also read about it in the laravels documentation about scoped events
I'm trying to broadcast an event in a case where two user share a conversation (like a chat) where only the two of the can access and get notified when a new message comes.
I think, after reading the documentation that the presence channel is the best option (private is for one people and the server and channel is for something plublic without checking ?)
So in my routes/channels.php I have something like this:
Broadcast::channel('conversation.{conversation}', function ($user, Conversation $conversation) {
if ($user->id === $conversation->user1_id || $user->id === $conversation->user2_id) {
return $user;
}
return null;
});
In the client side a Component I have:
Echo
.join('conversation.${conversation.id}')
.here((users) => {
this.usersInRoom = users;
})
.joining((user) => {
this.usersInRoom.push(user);
})
.leaving((user) => {
this.usersInRoom = this.usersInRoom.filter(u => u != user);
})
.listen('MessagePosted', (e) => {
this.messages.push({
id :e.message.id,
user_id :e.message.user_id,
conversation_id :e.message.conversation_id,
user :e.user,
text :e.message.text,
created_at :e.message.created_at,
updated_at :e.message.updated_at,
});
});
And the class that emit the even MessagePosted :
public function broadcastOn()
{
return new PresenceChannel('conversation.'.$this->message->conversation_id);
}
So I now that previously I used a PresenceChannel without any checking, so if two people where in there conversation they would get notification from everyone. not the right thing.
In the server side, I have the 'conversation.{conversation}' that was mentioned in the documentation to make a separated channel. But I also saw something like 'conversation.*'.
And on the client side I have join('conversation.${conversation.id}') but here I am not sure at all I just know that I have in the props (props : ['user', 'friend', 'conversation']) a conversation which is an object with the id of the conversation.
So When, when everyone was on the same channel with no restriction everything was working perfectly and now, I think I have an error which make the whole thing not work.
I have two 500 server side error when I load a client conversation :
ReflectionException in Broadcaster.php line 170:
Class Conversation does not exist
(And in the route/channels.php I import the Conversation class use App\Conversation;)
and
HttpException in Broadcaster.php line 154:
I found the following solution to my problem. I think I saw something in the documentation saying that you might need to use the Path of the class you want to broadcast. So I tried something like this :
In the routes/channel.php
Broadcast::channel('App.Conversation.{id}', function ($user, $id) {
$conversation = Conversation::findOrFail($id);
if ($user->id === $conversation->user1_id || $user->id === $conversation->user2_id) {
return $user;
}
return null;
});
In the client side in the vue component :
Echo
.join('App.Conversation.'+this.conversation.id)
...
In the class that emit the event MessagePosted :
public function broadcastOn()
{
return new PresenceChannel('App.Conversation.'.$this->message->conversation_id);
}