When i am broadcasting a TestEvent - i am getting the response on console - But when i am broadcasting notification - i am not getting it.
This is where i am broadcasting the notification
<?php
namespace App\Http\Controllers;
use App\Models\Like;
use App\Models\Post;
use App\Models\User;
use App\Events\TestEvent;
use Illuminate\Http\Request;
use App\Notifications\Post\PostLiked;
use Illuminate\Support\Facades\Notification;
class PostLikeController extends Controller
{
public function toggleLike(Post $post)
{
$like = Like::where([
'user_id' => auth()->id(),
'likeable_type' => Post::class,
'likeable_id' => $post->id
])->first();
if($like){
$like->delete();
}else{
$like = Like::create([
'user_id' => auth()->id(),
'likeable_type' => Post::class,
'likeable_id' => $post->id,
'is_like' => true
]);
// Notify Post Author
if($post->user_id != auth()->id()){
$post->load('user.media');
$post_author = User::find($post->user_id);
$post_author->notify(new PostLiked($post));
// broadcast(new TestEvent($post_author));
}
}
return back();
}
}
This is my PostLiked notification Class
<?php
namespace App\Notifications\Post;
use App\Models\Post;
use Illuminate\Bus\Queueable;
use App\Http\Resources\UserResource;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\BroadcastMessage;
class PostLiked extends Notification implements ShouldBroadcastNow
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct(public Post $post)
{
//
}
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['database', 'broadcast'];
}
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
'post_link' => route('posts.show', $this->post->uuid),
'message' => 'Liked your post',
'sender' => UserResource::make(auth()->user()),
];
}
/**
* Get the broadcastable representation of the notification.
*/
public function toBroadcast(object $notifiable): BroadcastMessage
{
return new BroadcastMessage([
'post_link' => route('posts.show', $this->post->uuid),
'message' => 'Liked your post',
'sender' => UserResource::make(auth()->user()),
]);
}
}
This is how i defined the channel
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
And this is how i am trying to receive the broadcasting
<script setup>
import { Link, router, usePage } from '@inertiajs/vue3';
import axios from 'axios';
import { ref, reactive, onMounted } from 'vue';
const user = usePage().props.auth.user
const unreadNotifications = ref([]);
const unreadNotificationCount = ref(0);
onMounted(async () => {
const response = await axios.get(route('user.notifications.tray'))
unreadNotifications.value = response.data
unreadNotificationCount.value = response.data.length
Echo.private(`App.Models.User.${user.id}`)
.notification((notification) => {
console.log(notification);
});
// Echo.private(`App.Models.User.2`)
// .listen( 'TestEvent' ,(event) => {
// console.log(event);
// });
})
// Notification Tray State
const notificationTray = reactive({
open: false,
handleChange() {
notificationTray.open = !notificationTray.open
},
reset() {
notificationTray.open = false
}
})
function markAllNotificationAsRead() {
// Preventing unnecessary request
if (!unreadNotifications.value.length) {
return;
}
router.post(route('user.notifications.mark_all_as_read'), {}, {
preserveScroll: true,
onSuccess: () => {
unreadNotificationCount.value = 0
}
})
}
</script>
<template>
<div class="relative inline-block">
<!-- Dropdown toggle button -->
<button @click="notificationTray.handleChange" v-click-away="notificationTray.reset"
class="relative z-10 block text-gray-700 rounded-full">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-5 sm:size-6 " :class="(notificationTray.open) ? 'stroke-blue-600' : ''">
<path stroke-linecap="round" stroke-linejoin="round"
d="M14.857 17.082a23.848 23.848 0 0 0 5.454-1.31A8.967 8.967 0 0 1 18 9.75V9A6 6 0 0 0 6 9v.75a8.967 8.967 0 0 1-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 0 1-5.714 0m5.714 0a3 3 0 1 1-5.714 0" />
</svg>
<p v-if="unreadNotificationCount > 0" class="absolute -top-2 -right-1 text-xs bg-red-500 p-2 text-white w-5 h-5 flex items-center justify-center rounded-full leading-none">{{ unreadNotificationCount }}</p>
</button>
<!-- Dropdown menu -->
<Transition name="slide-fade">
<div v-show="notificationTray.open"
class="absolute -right-7 lg:-right-40 top-14 lg:top-[4.7rem] z-20 w-72 overflow-hidden origin-top-right bg-white rounded-md shadow-lg sm:w-80 dark1:bg-gray-800">
<div class="py-2 max-h-96 md:max-h-[450px] overflow-x-hidden overflow-y-auto">
<!-- For no unread notification -->
<div v-show="unreadNotifications.length == 0" class="flex flex-col items-center py-5 space-y-3">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="size-5 md:size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9 3.75H6.912a2.25 2.25 0 0 0-2.15 1.588L2.35 13.177a2.25 2.25 0 0 0-.1.661V18a2.25 2.25 0 0 0 2.25 2.25h15A2.25 2.25 0 0 0 21.75 18v-4.162c0-.224-.034-.447-.1-.661L19.24 5.338a2.25 2.25 0 0 0-2.15-1.588H15M2.25 13.5h3.86a2.25 2.25 0 0 1 2.012 1.244l.256.512a2.25 2.25 0 0 0 2.013 1.244h3.218a2.25 2.25 0 0 0 2.013-1.244l.256-.512a2.25 2.25 0 0 1 2.013-1.244h3.859M12 3v8.25m0 0-3-3m3 3 3-3" />
</svg>
<p class="mx-2 text-xs text-gray-600 dark1:text-white font-bold">
You don't have any unread notification
</p>
</div>
<!-- Displaying all unread notifications -->
<template v-show="unreadNotifications.length > 0"
v-for="(notification, index) in unreadNotifications" :key="index">
<Link :href="notification.data.post_link"
class="flex items-center px-4 py-3 -mx-2 transition-colors duration-300 transform border-b border-gray-100 hover:bg-gray-50 dark1:hover:bg-gray-700 dark1:border-gray-700">
<img class="flex-shrink-0 object-cover w-8 h-8 mx-1 rounded-full"
:src="notification.data.sender.profileImgUrl" :alt="notification.data.sender.first_name" />
<p class="mx-2 text-xs text-gray-600 dark1:text-white">
<span class="font-bold">
{{ notification.data.sender.first_name }} {{ notification.data.sender.last_name }}
</span> {{ notification.data.message }} . {{ notification.created_at }}
</p>
</Link>
</template>
</div>
<!-- Actions -->
<div class="flex justify-between w-full">
<Link :href="route('user.notifications')"
class="block w-1/2 py-2 border-r-2 border-r-gray-500 font-medium text-xs text-center text-white bg-gray-800 dark1:bg-gray-700 hover:underline">
See all notifications
</Link>
<button @click.prevent = "markAllNotificationAsRead"
class="block w-1/2 py-2 font-medium text-xs text-center text-white bg-gray-800 dark1:bg-gray-700 hover:underline">
Mark all as read
</button>
</div>
</div>
</Transition>
</div>
</template>
<style scoped>
/*
Enter and leave animations can use different
durations and timing functions.
*/
.slide-fade-enter-active {
transition: all 0.2s ease-out;
}
.slide-fade-leave-active {
transition: all 0.2s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter-from,
.slide-fade-leave-to {
transform: translateY(-20px);
opacity: 0;
}
</style>
I am not getting where is the error.
Thanks in advance
Sorry for the delay on this! Let me know if you're still having the issue and I'll dive in and help out :)
Hi @alex Thanks for the reply.
Yes..i am.still facing the issue.....
Event is Broadcasting perfectly however, notifications are not broadcasting....
I would appreciated if you add few more episods on realtime with reverb course related to notification and model broadcasting.
Could you try to move the Echo connection outside of the onMounted hook temporarily?
onMounted(async () => {
const response = await axios.get(route('user.notifications.tray'))
unreadNotifications.value = response.data
unreadNotificationCount.value = response.data.length
Echo.private(`App.Models.User.${user.id}`)
.notification((notification) => {
console.log(notification);
});
// Echo.private(`App.Models.User.2`)
// .listen( 'TestEvent' ,(event) => {
// console.log(event);
// });
})
Like this:
Echo.private(`App.Models.User.${user.id}`)
.notification((notification) => {
console.log(notification);
});
onMounted(async () => {
const response = await axios.get(route('user.notifications.tray'))
unreadNotifications.value = response.data
unreadNotificationCount.value = response.data.length
// Echo.private(`App.Models.User.2`)
// .listen( 'TestEvent' ,(event) => {
// console.log(event);
// });
})
Just purely to see if they come through.
Sorry, missed this! If you’re still having trouble please link to the repo here.