Comment notifier ses utilisateurs sur plusieurs canaux

Introduction à la gestion de notifications avec Laravel

Qui suis-je ?

Johann Pardanaud

Développeur web chez Batch.com

Contributeur open source et auteur de plusieurs projets dont :

Notifier quelqu'un est une tâche complexe

  • Comment notifier ?
  • Quelles informations fournir ?
  • À quelles occasions ?

Qu'est-ce qu'une notification ?

(dans le contexte de Laravel)

Il s'agit d'un message adressé à un utilisateur suite à un évènement.

Selon le channel, la notification peut être enrichie avec du contenu supplémentaire.

Structure d'une notification

namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class RegistrationCompleted extends Notification
{
    public function via($notifiable): array
    {
        return ['mail'];
    }

    public function toMail($notifiable): MailMessage
    {
        //
    }
}
php artisan make:notification
namespace App\Notifications;

use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\SlackMessage;

class RegistrationCompleted extends Notification
{
    public function via($notifiable): array
    {
        return $notifiable->prefers_slack ? ['slack'] : ['mail'];
    }

    public function toSlack($notifiable): SlackMessage
    {
        //
    }
}

Envoyer une notification

$user->notify(new RegistrationCompleted);
$user->notify(new MessageReceived($from));
namespace App\Notifications;

use App\User;
use Illuminate\Notifications\Notification;

class MessageReceived extends Notification
{
    private $from;

    public function __construct(User $from)
    {
        $this->from = $from;
    }

    public function toSlack($notifiable): SlackMessage
    {
        // $this->from
    }
}

Différer l'envoi

Avec les queues Laravel

namespace App\Notifications;

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

class RegistrationCompleted extends Notification implements ShouldQueue
{
    use Queueable;

    // ...
}
$notification = (new RegistrationCompleted)
    ->onQueue('notifications')
    ->delay(now()->addMinutes(30));

$user->notify($notification);
$user->notify(new RegistrationCompleted);

Exploiter les autres modèles

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;

class Project extends Model
{
    use Notifiable;

    public function owner()
    {
        return $this->belongsTo(App\User::class);
    }

    public function routeNotificationForMail()
    {
        return $this->owner->email;
    }
}
$project->notify(new ArchivedProject);
namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;

class Project extends Model
{
    use Notifiable;

    public function editors()
    {
        return $this->belongsToMany(App\User::class);
    }

    public function notify($notification): void
    {
        \Notification::send($this->editors, $notification);
    }
}

Les channels fournis

Laravel est fourni avec des channels basiques : emails, SMS et messages Slack.

Et propose aussi deux channels plus avancés :

  • La communication via les websockets
  • Le stockage dans une base de données

Emails, SMS, Slack

Construction des messages simplifiée avec des builders pour ces 3 channels.

Tout se paramètre dans les fichiers de configuration de votre app.

Emails

public function toMail($notifiable)
{
    return (new MailMessage)
        ->subject('Notifications Laravel')
        ->greeting("Bonjour {$notifiable->first_name}!")
        ->line(
            'J\'ai cru comprendre que vous vouliez en '
            .'savoir plus sur les notifications Laravel ?'
        )
        ->line('Voici un talk qui devrait vous intéresser :')
        ->action('Consulter le talk', $this->url)
        ->line('À bientôt !');
}
php artisan vendor:publish --tag=laravel-notifications

SMS

public function toNexmo($notifiable)
{
    return (new NexmoMessage)
        ->content('Bienvenue chez nous ! 🎉')
        ->unicode();
}

Slack

public function toSlack($notifiable)
{
    return (new SlackMessage)
        ->success()
        ->content('Voici les dernières statistiques :')
        ->attachment(function ($attachment) {
            $date = date('d/m/Y');
            $url = 'https://analytics.google.com/analytics/web';

            $attachment->title("Stats du $date", $url)
                ->fields([
                    'Utilisateurs' => $this->users,
                    'Nouveaux utilisateurs' => $this->newUsers,
                ]);
        });
}

Notifier sur les websockets

Réception de la notification avec Laravel Echo :

public function toBroadcast($notifiable)
{
    return new BroadcastMessage([
        'from' => $this->from,
        'content' => $this->content,
    ]);
}
Echo.private(`App.User.${userId}`)
    .notification(notification => {
        new Notification(
            `Message de ${notification.from.first_name}`,
            { body: notification.content }
        );
    });

Stocker les notifications

php artisan notifications:table
$user->notifications()->firstOrFail()->data['project_id'];

$user->unreadNotifications->markAsRead();
public function toDatabase($notifiable)
{
    return ['project_id' => $this->project->id];
}

Traduire le contenu

$notification = (new RegistrationCompleted)->locale('fr');
$user->notify($notification);
public function toMail($notifiable)
{
    return (new MailMessage)
        ->subject(__('register.mail.subject', [], $this->locale))
        ->greeting(
            __(
                'register.mail.greeting',
                ['name' => $notifiable->first_name],
                $this->locale
            )
        )
        ->line(__('register.mail.content', [], $this->locale))
        ->line(__('register.mail.see_you', [], $this->locale));
}

Création d'un channel custom

Envoi de notifications push avec Batch (Github)

Plus de channels disponibles sur

laravel-notification-channels.com

Questions

Comment notifier ses utilisateurs sur plusieurs canaux

By Johann Pardanaud

Comment notifier ses utilisateurs sur plusieurs canaux

  • 174