DEV Community

ashrakt
ashrakt

Posted on • Edited on

Laravel Real-time

What Are Notifications in Laravel?
Laravel notification is a way to send a message to your users. Think of it as a central hub for all your app's alerts. Instead of writing separate code for emails, text messages, or in-app alerts, Laravel gives you a single, clean way to handle them all. You write the message once, and Laravel sends it through whatever channels you choose.

Types of Notifications
Laravel has several built-in notification types, each for a different purpose:

  1. Mail Notifications:
    These send a standard email. They're perfect for important updates like a new invoice or a password reset link.

  2. Database Notifications:
    This type saves a record of the notification in your database. It's used for the notifications you see inside an app. Users can see their notification history and mark them as read.

  3. SMS Notifications:
    send text messages directly to a user's phone. This is perfect for things that need immediate attention, like verification codes (OTP). Laravel supports this through services like Vonage and Twilio.

  4. Slack Notifications:
    send messages to Slack channels or to team members directly. This is great for sending internal alerts, like error logs or important system updates, helping development teams stay informed.

  5. Broadcast Notifications: This is the key to real-time notifications. It sends the notification data to a service like Pusher or Laravel Echo. This allows a user's browser to get an instant alert without having to refresh the page. This is what makes real-time functionality possible.


*How to Send a Notification to an Admin When a New User Registers
*

I- Prepare the Database
First, you need a table to save the notifications. Use this command to create a migration file:

  • php artisan notifications:table

Then, run the migration to create the table named notifications in your database:
php artisan migrate


  • Make Your Admin Model Notifiable By default, Laravel's User model is already notifiable. But if you have a separate Admin model, you need to add the Notifiable trait to it. This gives the Admin model the superpower to receive notifications.


  • Create the Notification class
    Next, create the notification class that will define the content. This example will create a notification for when a new user signs up.

  • php artisan make:notification NewUserRegisteredNotification

Open the new file app/Notifications/NewUserRegisteredNotification.php.

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NewUserRegisteredNotification extends Notification
{
    use Queueable;
    public $user;

    public function __construct($newUser)
    {
        $this->user = $newUser;
    }

    public function via(object $notifiable): array
    {
        return ['database'];
    }


    // public function toMail(object $notifiable): MailMessage
    // {
    //     return (new MailMessage)
    //         ->line('The introduction to the notification.')
    //         ->action('Notification Action', url('/'))
    //         ->line('Thank you for using our application!');
    // }


    public function toArray(object $notifiable): array
    {
        return [
            "name"    => $this->user->name,
            "email"   => $this->user->email,
            "message" => "new user registered",
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

__construct()
This function is the "constructor" of the class. You use it to pass any data that the notification needs before it's sent.

via(object $notifiable): array
This function determines the channels the notification will be sent through. It simply returns an array with the names of the channels you want to use, like mail, database, or slack.

toMail(object $notifiable): MailMessage
This function is specifically for email notifications. If the via() function returns mail, this function will be used to build the email message. Here, you define the subject, the body text, and any buttons that will appear in the email.

toArray(object $notifiable): array
This function is a generic way to convert the notification into an array. It's used by different channels, like database and broadcast, to either save the notification or send it as data.


We want to store this notification in the database, so we'll use the database channel and define the data to be stored.


  • calling notification

If you have just one admin to notify.

public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:' . User::class],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        event(new Registered($user));

        $admin = Admin::find(1);
        $admin->notify(new NewUserRegisteredNotification($user));

        Auth::login($user);

        return redirect(RouteServiceProvider::HOME);
    }
Enter fullscreen mode Exit fullscreen mode
  • register form

  • notifications table

you can use another way
Notification::send($admin, new NewUserRegisteredNotification($user));


  • displaying notification
<li class="nav-item nav-notif">
            <a class="nav-link text-muted my-2 notificationIcon" href="./#" data-toggle="modal"
                data-target=".modal-notif">
                <span class="fe fe-bell fe-16"></span>
                <span class="dot dot-md text-danger"
                    id="notificationIconCounter">{{ count(Auth::guard('admin')->user()->unreadNotifications) }}</span>
            </a>
        </li>
        {{-- Notification Modal --}}
        <div class="modal fade modal-notif modal-slide" tabindex="-1" role="dialog"
            aria-labelledby="defaultModalLabel" aria-hidden="true">
            <div class="modal-dialog modal-sm" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="defaultModalLabel">Notifications</h5>
                        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                            <span aria-hidden="true">&times;</span>
                        </button>
                    </div>
                    <div class="modal-body" id="notificationIconModal">
                        @if (count(Auth::guard('admin')->user()->notifications) > 0)
                            <div class="list-group list-group-flush my-n3">
                                @foreach (Auth::guard('admin')->user()->notifications->take(5) as $notification)
                                    <div
                                        class="list-group-item @if ($notification->unread()) bg-light @else bg-transparent @endif ">
                                        <div class="row align-items-center">
                                            <div class="col-auto">
                                                <span class="fe fe-box fe-24"></span>
                                            </div>
                                            <div class="col">
                                                {{-- <small><strong>Package has uploaded successfull</strong></small> --}}
                                                <div class="my-0 text-muted small">
                                                    {{ $notification->data['message'] }}
                                                </div>
                                                <small
                                                    class="badge badge-pill badge-light text-muted">{{ $notification->created_at->diffForHumans() }}</small>
                                            </div>
                                        </div>
                                    </div>
                                @endforeach
                            </div>
                        @endif <!-- / .list-group -->
                    </div>
                    <div class="modal-footer" id="clearNotification">
                        <button type="button" class="btn btn-secondary btn-block" data-dismiss="modal">Clear
                            All</button>
                    </div>
                </div>
            </div>
        </div>
Enter fullscreen mode Exit fullscreen mode
<script>
    $("document").ready(function() {
        // mark all notifications to read
        $(document).on('click', ".notificationIcon", function() {
            $.ajax({
                url: {{ Illuminate\Support\Js::from(route('admin.notifications.read')) }},
                method: 'get',
                success: function(data) {
                    $("#notificationIconCounter").load(" #notificationIconCounter > *");
                    $("#notificationIconModal").load(" #notificationIconModal > *");
                },
                error: function() {
                    alert("please try again");
                }
            });
        });



        // clear all notification
        $(document).on('click', "#clearNotification", function() {
            $.ajax({
                url: {{ Illuminate\Support\Js::from(route('admin.notifications.clear')) }},
                method: 'get',
                success: function(data) {
                    $("#notificationIconCounter").load(" #notificationIconCounter > *");
                    $("#notificationIconModal").load(" #notificationIconModal > *");
                },
                error: function() {
                    alert("please try again");
                }
            });
        });
    });
</script>
Enter fullscreen mode Exit fullscreen mode

basic configurations
Before broadcasting any events, you will first need to register the App\Providers\BroadcastServiceProvider. In new Laravel applications, you only need to uncomment this provider in the providers array of your config/app.php configuration file. This BroadcastServiceProvider contains the code necessary to register the broadcast authorization routes and callbacks.

The config/broadcasting.php file is the central configuration hub for Laravel's broadcasting system. Its main role is to tell Laravel which broadcasting service to use and how to connect to it.


Getting Started with broadcast driver (Pusher):

These are the simple steps to set up your account and get your API keys.

  1. Create Your Pusher Account
    Go to the Pusher website (pusher.com).

  2. Choose a Pusher Product
    After signing up, you'll be asked to choose a product.

Select Channels (this is the service used for Laravel's real-time events).

  1. Create a New Application You'll be prompted to Create a New App. Name your app (e.g., laravel-broadcast-app). Select a Cluster (a server region, like eu or us2)—choose one closest to your users for better performance.


  1. Get Your App Keys Once the app is created, you'll be taken to the App Keys section

Copy these keys. You will need to paste them into your Laravel project's .env file to connect your application to Pusher.


Creating a Broadcast Event

1- Generate the Event Class
First, you need to create a new Event class using the Artisan command. We'll name this event NewUserRegisteredEvent.
php artisan make:event NewUserRegisteredEvent

This command creates a new file at app/Events/NewUserRegisteredEvent.php.

2- Implement the Broadcast Interface
Open the newly created file (app/Events/NewUserRegisteredEvent.php). To make any event broadcastable, its class must implement the ShouldBroadcast interface.

  • Use the Interface: Add use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

  • Implement: Add implements ShouldBroadcast to the class definition.

3- Dispatch the Event
Finally, you need to fire the event from your Laravel code (e.g., from a Controller after a user register).

These two lines of code are the ways you trigger (or "fire") the broadcasting process for your event in Laravel.


    public function store(Request $request): RedirectResponse
    {
        $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:' . User::class],
            'password' => ['required', 'confirmed', Rules\Password::defaults()],
        ]);

        $user = User::create([
            'name' => $request->name,
            'email' => $request->email,
            'password' => Hash::make($request->password),
        ]);

        event(new Registered($user));

        $admin = Admin::find(1);
        // $admin->notify(new NewUserRegisteredNotification($user));
        Notification::send($admin, new NewUserRegisteredNotification($user));


        // trigger (or "fire") the broadcasting process
        NewUserRegisteredEvent::dispatch($user);
        // broadcast(new NewUserRegisteredEvent($user));

        Auth::login($user);
        return redirect(RouteServiceProvider::HOME);
    }
Enter fullscreen mode Exit fullscreen mode

recievers

  • pusher
  • Laravel Echo

using pusher

1- Install the Pusher PHP SDK

laravel pusher documentation

composer require pusher/pusher-php-server

pusher reciever

  • Subscribe to events on the client.
  <script src="https://js.pusher.com/8.2.0/pusher.min.js"></script>
    <script>
        // Enable pusher logging - don't include this in production
        Pusher.logToConsole = false;

        var pusher = new Pusher("{{ env('PUSHER_APP_KEY') }}", {
            cluster: 'eu'
        });

        var channel = pusher.subscribe('new_user_channel');
        channel.bind('App\\Events\\NewUserRegisteredEvent', function(data) {
            console.log(data['message']);
            let currentCount = parseInt($("#notificationIconCounter").text()) || 0;
            let newCount = currentCount + 1;
            $("#notificationIconCounter").text(newCount);
        });
    </script>
Enter fullscreen mode Exit fullscreen mode

-You will need to update your Laravel project's .env file BROADCAST_DRIVER=pusher.

test your code:


using Laravel Echo

Laravel Echo is a JavaScript library that makes it painless to subscribe to channels and listen for events broadcast by your server-side broadcasting driver. You may install Echo via the NPM package manager.

To successfully switch to Laravel Echo, you must comment out or remove the direct Pusher client initialization script from your HTML or Blade files.

1- install package
npm install --save-dev laravel-echo pusher-js

2- Configure .env
Add your Pusher credentials (Keys, Secret, and Cluster) to your .env file.

BROADCAST_DRIVER=pusher
PUSHER_APP_ID=YOUR_APP_ID
PUSHER_APP_KEY=YOUR_APP_KEY
PUSHER_APP_SECRET=YOUR_APP_SECRET
PUSHER_APP_CLUSTER=eu or mt1 or ap2 
Enter fullscreen mode Exit fullscreen mode

3- Configure Echo
Open the file resources/js/bootstrap.js (or app.js) and uncomment the Echo block, using your .env variables via the VITE_ prefix:

4- Load the compiled and necessary assets for the primary entry point file located at resources/js/app.js."

  • In Development run npm run dev
  • In Production run npm run build

5- Listening for Events
you are ready to start listening for events that are broadcast from your Laravel application. First, use the channel method to retrieve an instance of a channel, then call the listen method to listen for a specified event.

Top comments (0)