Laravel 10

Cours Laravel 10 – les notifications

On a vu dans ce cours comment envoyer un email avec Laravel. Mais on dispose aussi d’un système complet de notifications, par exemple par SMS, qui inclue aussi les emails ou même la base de données.

Classiquement, une notification est un court message pour informer un utilisateur qu’il s’est passé quelque chose qui le concerne dans l’application.

Par exemple, une donnée sensible a été mise à jour, on envoie un SMS par sécurité en informant l’utilisateur de ce changement et, si ce n’est pas lui qui l’a effectué, il peut alors intervenir.

Évidemment, pour tout ce qui n’est pas email ou base de données, il faut utiliser un service externe. Il y a un site dédié pour tous les drivers existants et la liste est longue !

Organisation du code

Il y a une commande d’artisan pour créer une notification :

php artisan make:notification MaNotification

Les notifications se trouvent dans le dossier app/Notifications :

Ce dossier n’existe pas dans l’installation de base de Laravel, il est ajouté lorsqu’on crée la première notification avec Artisan.

Bien sûr, pour les packages, les notifications se situent dans un dossier du package.

Le renouvellement du mot de passe

On a vu en détail le renouvellement du mot de passe dans ce chapitre. J’ai alors précisé qu’on envoyait un email par le système de notification en mentionnant que je vous en parlerai plus tard. C’est ce que je vais faire maintenant.

On a vu que Laravel, après la demande de renouvellement de l’utilisateur, expédie ce genre d’email :

Par défaut, la classe de notification se situe dans le framework :

Avec ce code (extrait) :

<?php

namespace Illuminate\Auth\Notifications;

use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Lang;

class ResetPassword extends Notification
{
    ...

    /**
     * Get the notification's channels.
     *
     * @param  mixed  $notifiable
     * @return array|string
     */
    public function via($notifiable)
    {
        return ['mail'];
    }

    /**
     * Build the mail representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    public function toMail($notifiable)
    {
        if (static::$toMailCallback) {
            return call_user_func(static::$toMailCallback, $notifiable, $this->token);
        }

        return $this->buildMailMessage($this->resetUrl($notifiable));
    }

    /**
     * Get the reset password notification mail message for the given URL.
     *
     * @param  string  $url
     * @return \Illuminate\Notifications\Messages\MailMessage
     */
    protected function buildMailMessage($url)
    {
        return (new MailMessage)
            ->subject(Lang::get('Reset Password Notification'))
            ->line(Lang::get('You are receiving this email because we received a password reset request for your account.'))
            ->action(Lang::get('Reset Password'), $url)
            ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))
            ->line(Lang::get('If you did not request a password reset, no further action is required.'));
    }

    ...
}

Comme c’est une notification par email, on a une méthode toMail. D’autre part, on précise dans la méthode via qu’on retourne un email. La classe MailMessage offre un certain nombre de méthodes bien pratiques comme :

  • line : pour écrire une ligne
  • action : pour afficher un bouton
  • from : pour définir l’adresse de l’expéditeur
  • subject : pour définir le sujet
  • cc et bcc : pour faire des copies
  • attach : pour joindre un document
  • priority : pour fixer la priorité…

Vous constatez qu’on a une mise en forme de l’email plutôt esthétique. Cette mise en forme est issue d’une vue par défaut dans le framework :

Si vous voulez modifier cette mise en forme, il faut publier cette vue :

php artisan vendor:publish --tag=laravel-notifications

Vous retrouvez alors la vue dans le dossier resources/views/vendor/notifications :

Vous pouvez vous demander à présent comment est effectivement commandée cette notification. Ça se passe dans le trait CanResetPassword avec la méthode notify :

<?php

namespace Illuminate\Auth\Passwords;

use Illuminate\Auth\Notifications\ResetPassword as ResetPasswordNotification;

trait CanResetPassword
{
    ...

    public function sendPasswordResetNotification($token)
    {
        $this->notify(new ResetPasswordNotification($token));
    }
}

Un exemple

Comme rien ne vaut un exemple, on va en réaliser un. On va à nouveau partir d’une installation vierge de Laravel avec Breeze. On va décider d’envoyer un email à un utilisateur qui s’enregistre avec succès. On commence par créer la notification avec Artisan :

php artisan make:notification RegisteredNotification

On a ce code à la création :

<?php

namespace App\Notifications;

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

class RegisteredNotification extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the notification's delivery channels.
     *
     * @return array<int, string>
     */
    public function via(object $notifiable): array
    {
        return ['mail'];
    }

    /**
     * Get the mail representation of the notification.
     */
    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!');
    }

    /**
     * Get the array representation of the notification.
     *
     * @return array<string, mixed>
     */
    public function toArray(object $notifiable): array
    {
        return [
            //
        ];
    }
}

On va modifier la fonction toMail pour changer le message :

public function toMail($notifiable)
{
    return (new MailMessage)->line('Vous avez bien été enregistré sur notre site !');
}

Il ne reste plus qu’à envoyer la notification à partir de la méthode store du contrôleur RegisteredUserController :

use App\Notifications\RegisteredNotification;

...

protected function store(Request $request): RedirectResponse
{
    ...
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => Hash::make($request->password),
    ]);

    $user->notify(new RegisteredNotification());

    ...
}

Maintenant quand un utilisateur s’enregistre il reçoit un email :

C’est tout simple !

Si on veut le texte de fond en français, ou tout autre langage, on peut publier le template comme on l’a vu plus haut :

Vous pouvez d’ailleurs remarquer que ce template est déjà prévu i18n. For example pour l’accueil, on a :

@lang('Hello!')

Autrement dit, comme on l’a vu dans l’article précédent sur la localisation, si on a le fichier de langue :

On y trouve ce code :

{
    ...
    "Hello!": "Bonjour !"
}

Il suffit de préciser la langue dans le fichier config/app.php :

'locale' => 'fr',

Et maintenant dans l’email :

Il y aurait encore beaucoup à dire sur les notifications au-delà des exemples de ce chapitre, reportez-vous à la documentation officielle pour en savoir plus.

En résumé

  • Laravel comporte un système complet et performant de notifications.
  • On peut envoyer des emails avec les notifications, leur mise en forme est facilitée par la présence de puissantes méthodes et d’un template qu’on peut personnaliser.
Print Friendly, PDF & Email

2 commentaires

  • Hyppolite

    Je voudrais ajouter quelque chose, l’objet de l’email n’étant pas traduit, j’ai dû ajouter dans le fichier fr.json du dossier lang/ la ligne
    « Registered Notification »: « Notification d’enregistrement »,
    puis utiliser la méthode
    ->Subject(Lang::get(‘Registered Notification’))
    de la classe MailMessage en précisant l’espace de nom
    use Illuminate\Support\Facades\Lang;
    afin d’avoir une traduction française de l’objet de l’email d’enregistrement 😉

Laisser un commentaire