Dans la plupart des exemples Laravel sur le web liés à l'envoi de notifications, je les vois souvent envoyées directement dans les actions des contrôleurs. Bien que cela convienne parfaitement pour un projet simple, il peut s'avérer plus difficile de gérer des projets plus volumineux, avec beaucoup de notifications et de canaux différents.
Dans cet article, je vais vous montrer un moyen simple de refactoriser et de regrouper les notifications afin qu'elles soient plus faciles à gérer.
Commençons par l'exemple de code suivant où nous souhaitons envoyer une notification SMS à un utilisateur lorsqu'un nouveau message est créé et quand un message existant est liké.
namespace App\Http\Controllers;
use App\Notifications\PostCreated;
use App\Notifications\PostLiked;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Store a new post.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// Create the post..
$user->notify(new PostCreated($post));
}
/**
* Like the post.
*
* @param Post $post
*
* @return \Illuminate\Http\Response
*/
public function like(Post $post)
{
// Like the post..
$user->notify(new PostLiked($post));
}
}
Envoi d'événements
Au lieu d'envoyer la notification directement à partir de l'action du contrôleur, nous allons créer et envoyer un événement.
En utilisant php artisan make:event, j'ai créé deux événementsPostWasCreated et PostWasLiked correspondant aux notifications que nous souhaitons envoyer.
Nous pouvons maintenant remplacer les appels de notification par les nouveaux déclencheurs d'événements dans notre contrôleur.
namespace App\Http\Controllers;
use App\Events\PostWasCreated;
use App\Events\PostWasLiked;
use App\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Store a new post.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
// Create the post..
event(new PostWasCreated($post));
}
/**
* Like the post.
*
* @param Post $post
*
* @return \Illuminate\Http\Response
*/
public function like(Post $post)
{
// Like the post..
event(new PostWasLiked($post));
}
}
Le code des deux événements est identique, c'est un simple value object contenant l'instance du Post.
namespace App\Events;
use App\Post;
use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
class PostWasCreated
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* The post.
*
* @var Post
*/
public $post;
/**
* Create a new event instance.
*
* @param Post $post
*/
public function __construct(Post $post)
{
$this->post = $post;
}
}
Création d'un event subscriber
Pour découpler l'action de notification de l'événement réel, nous allons créer un nouvel event subscriber qui écoute ces événements et envoie les notifications.
namespace App\Listeners;
use App\Events\PostWasCreated;
use App\Events\PostWasLiked;
use App\Notifications\PostCreated;
use App\Notifications\PostLiked;
class SmsNotifier
{
/**
* Sends a notification to the user.
*
* @param PostWasCreated $event
*/
public function onPostCreated(PostWasCreated $event)
{
// $user comes from somewhere, maybe the site admin
$user->notify(new PostCreated($event->post));
}
/**
* Sends a notification to the user.
*
* @param PostWasLiked $event
*/
public function onPostLiked(PostWasLiked $event)
{
// $user comes from somewhere, maybe $post->owner
$user->notify(new PostLiked($event->post));
}
/**
* Register the listeners for the subscriber.
*
* @param \Illuminate\Events\Dispatcher $events
*/
public function subscribe($events)
{
$events->listen(PostWasCreated::class, 'App\Listeners\SmsNotifier@onPostCreated');
$events->listen(PostWasLiked::class, 'App\Listeners\SmsNotifier@onPostLiked');
}
}
Conclusion
La chose intéressante à propos de l’utilisation d’un event subscriber est que vous groupez les notifications dans la même classe, ce qui sera beaucoup plus facile à gérer. En outre, vous pouvez désactiver toutes les notifications simplement en désactivant le listener, au lieu de devoir retrouver chaque appel de la fonction notify(). Si vous utilisez différents types de notifications et de canaux, vous pouvez les regrouper dans plusieurs listeners, un pour chaque type de canal, afin de pouvoir les contrôler indépendamment.