Centralize your notification and job handling

Sospeter Mong'are - Sep 9 - - Dev Community

To simplify sending multiple email notifications after various events (like user creation, password resets, etc.), you can take a few steps to centralize your notification and job handling. This approach will make your work easier and more scalable without having to create a separate job or notification for each event.

Strategies to Simplify Email Notification Handling:

  1. Use a Generalized Email Notification Job.
  2. Leverage Event-Listener Architecture.
  3. Group Similar Notifications.

1. Create a Generalized Email Notification Job:

Instead of creating separate jobs for each notification, you can create a single reusable job that takes the notification and the user as parameters. This way, the same job can be used to handle different notifications.

Generalized SendEmailNotificationJob:

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Notifications\Notification;
use App\Models\User;

class SendEmailNotificationJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $user;
    public $notification;

    /**
     * Create a new job instance.
     *
     * @param  User $user
     * @param  Notification $notification
     * @return void
     */
    public function __construct(User $user, Notification $notification)
    {
        $this->user = $user;
        $this->notification = $notification;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // Send the notification
        $this->user->notify($this->notification);
    }
}
Enter fullscreen mode Exit fullscreen mode

With this generalized job, you can dispatch different types of email notifications using the same job:

Example Usage:

use App\Jobs\SendEmailNotificationJob;
use App\Notifications\UserWelcomeNotification;
use App\Models\User;

$user = User::find(1); // Example user

// Dispatch a welcome email notification
SendEmailNotificationJob::dispatch($user, new UserWelcomeNotification());

// Dispatch a password reset notification
SendEmailNotificationJob::dispatch($user, new PasswordResetNotification());
Enter fullscreen mode Exit fullscreen mode

2. Leverage Event-Listener Architecture:

Instead of manually dispatching jobs after each event, Laravel’s event-listener architecture allows you to automatically trigger notifications and jobs based on specific events (like user creation).

Step 1: Define Events:

You can define an event such as UserCreated:

php artisan make:event UserCreated
Enter fullscreen mode Exit fullscreen mode

Example UserCreated Event:

namespace App\Events;

use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class UserCreated
{
    use Dispatchable, SerializesModels;

    public $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Listeners:

You can create a listener that sends a notification when the event is fired:

php artisan make:listener SendUserWelcomeNotification --event=UserCreated
Enter fullscreen mode Exit fullscreen mode

Example Listener:

namespace App\Listeners;

use App\Events\UserCreated;
use App\Jobs\SendEmailNotificationJob;
use App\Notifications\UserWelcomeNotification;

class SendUserWelcomeNotification
{
    public function handle(UserCreated $event)
    {
        // Dispatch the email notification job
        SendEmailNotificationJob::dispatch($event->user, new UserWelcomeNotification());
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Fire Event on User Creation:

Whenever a user is created, you can fire the event, and Laravel will automatically handle the rest:

use App\Events\UserCreated;

$user = User::create($data);
event(new UserCreated($user));
Enter fullscreen mode Exit fullscreen mode

This approach allows you to decouple the logic of handling notifications from your business logic, making the system more scalable.

3. Group Similar Notifications:

If you have many similar notifications (e.g., user-related notifications like welcome emails, password resets, etc.), you can create a Notification Service that handles all user notifications in a centralized way.

Example NotificationService:

namespace App\Services;

use App\Models\User;
use App\Jobs\SendEmailNotificationJob;
use App\Notifications\UserWelcomeNotification;
use App\Notifications\PasswordResetNotification;

class NotificationService
{
    public function sendUserWelcomeEmail(User $user)
    {
        SendEmailNotificationJob::dispatch($user, new UserWelcomeNotification());
    }

    public function sendPasswordResetEmail(User $user)
    {
        SendEmailNotificationJob::dispatch($user, new PasswordResetNotification());
    }

    // You can add more methods for different types of notifications
}
Enter fullscreen mode Exit fullscreen mode

Example Usage:

In your controllers or event listeners, you can now simply call the service:

$notificationService = new NotificationService();
$notificationService->sendUserWelcomeEmail($user);
Enter fullscreen mode Exit fullscreen mode

Conclusion:

  • Single Job: You can use a generalized job (SendEmailNotificationJob) to handle different types of notifications.
  • Event-Listener Architecture: Utilize Laravel's event-listener system to automatically trigger notifications based on system events.
  • Centralized Notification Service: Group similar notifications in a service for better management and reusability.

This approach helps keep your code DRY (Don’t Repeat Yourself) and makes it easier to maintain when you have multiple email notifications to send.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .