Now, back to notifications
Now let's add a space in the navigation bar to display our notifications.
In resources/views/layouts/app.blade.php add the code below so we can use the material icons:
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
Let's create the "notifications" component:
php artisan make:livewire components.notification
In resources/views/livewire/layout/navigation.blade.php add:
@livewire('components.notification')
@livewire('components.notification')
Let's incorporate Laravel Echo to monitor notification events. This way, as soon as a notification is received, we can dynamically reload the notifications and post listing components.
<script>
document.addEventListener('DOMContentLoaded', () => {
Echo.private('App.Models.User.{{auth()->user()->id}}')
.notification(() => {
Livewire.dispatch('refreshNotification');
Livewire.dispatch('refreshPostList');
});
});
</script>
In resources/views/livewire/components/notification.blade.php:
<div>
<x-dropdown align="right" width="48">
<x-slot name="trigger">
<button
class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
<span class="rounded-full p-1 bg-red-500 text-white">17</span>
<span class="material-symbols-outlined">
notifications
</span>
</button>
</x-slot>
<x-slot name="content">
<div class="p-3 text-center">
<p>some notifications</p>
</div>
</x-slot>
</x-dropdown>
</div>
Notification Class
As we are going to send our notifications via the database channel, we need to create the notifications table:
php artisan notifications:table
php artisan migrate
Now let's create a notification class:
php artisan make:notification PostCreated
A new directory containing our class will be created:
In app/Notifications/PostCreated.php we will add the broadcast settings:
The constructor:
public $userId;
public $dataNotify;
/**
* Create a new notification instance.
*/
public function __construct($userId, $dataNotify)
{
$this->userId = $userId;
$this->dataNotify = $dataNotify;
}
/**
* Get the notification's delivery channels.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return ['broadcast', 'database'];
}
public function broadcastType()
{
return 'broadcast.message';
}
public function toBroadcast(object $notifiable): BroadcastMessage
{
return (new BroadcastMessage($this->dataNotify))->onConnection('database');
}
public function broadcastOn(): Channel
{
return new PrivateChannel("App.Models.User.{$this->userId}");
}
To send notifications, we will choose to use the Notifiable trait, which is already incorporated into our User model by default. This gives us an efficient, out-of-the-box approach. For more information about how to use this trait: https://laravel.com/docs/10.x/notifications#using-the-notifiable-trait
In app/Livewire/Posts/PostCreate.php we will add the action of notifying users anytime they have been tagged:
if ($this->state['tagged_user_id']) {
$taggedUser = User::query()->find($this->state['tagged_user_id']);
$taggedUser?->notify(new PostCreated($taggedUser['id'], $this->state));
}
The documentation explains the correct way to retrieve user notifications https://laravel.com/docs/10.x/notifications#accessing-the-notifications.
Let's add notification retrieval logic to app/Livewire/Components/Notification.php:
protected $listeners = [
'refreshNotification' => '$refresh'
];
public $notifications;
public $notificationsCounter;
public function getNotifications()
{
$this->notifications = auth()->user()->unreadNotifications;
$this->notificationsCounter = $this->notifications->count();
}
public function render()
{
$this->getNotifications();
return view('livewire.components.notification');
}
And let's modify the blade to display the notification counter:
<div>
<x-dropdown align="right" width="48">
<x-slot name="trigger">
<button
class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
@if($notificationsCounter)
<span class="rounded-full p-1 bg-red-500 text-white">{{$notificationsCounter}}</span>
@endif
<span class="material-symbols-outlined">
notifications
</span>
</button>
</x-slot>
<x-slot name="content">
@foreach($notifications as $notification)
<div class="p-3 text-center">
<p>You have been tagged in a new post!</p>
</div>
@endforeach
</x-slot>
</x-dropdown>
</div>
Let's start our worker:
php artisan queue:work
At this moment, our notifications are already being processed in queues and being directed in real time to marked users, as follows:
Conclusion
We were able to build, step by step, the real-time notification functionality using Laravel and Livewire, following only the official documentation. Despite the success, there are still several possible features to improve the project, such as:
- Creation of the validation layer.
- Creation of the repository layer.
- Pass data to the notification, such as the name of the person who tagged the user.
- Mark notifications as read.
I'm leaving the repository link for anyone interested: https://github.com/northoniserhardt/still-loving-docs
Beyond this, you are the one who decides! Thank you very much for following the tutorial.
Top comments (0)