Le design pattern Observer avec Symfony2

Rappelez-vous, dans l’article précédent, j’ai présenté le design pattern Observer, mais avec l’implémentation de la Bibliothèque standard Spl.

En voici l’implémentation avec Symfony2.

Les changements

  • Suppression des interfaces et classes abstraites
  • Mise en place d’un event pour l’observable (le sujet)
  • Mise en place de listeners (ou de subscribers) pour les observers (les observateurs)
  • L’attribut changed disparait dans cette implémentation (mais vous pouvez le réinstaurer bien sûr)

Let’s go! Symfony2 rocks!!!

1) Création de l’event DonneesMeteoEvent

C’est nouveau mais indispensable lorsque l’on utilise des events en Symfony2. Rappelez-vous, pour l’authentification sans FosUserBundle, j’avais aussi créé un event qui ne faisait que renvoyer l’entité. Ici, c’est pareil, mon event prend dans son constructeur mon observable, et me le rend par un getter.

2) Créons notre event de mise à jour des mesures

3) Créons la classe concrète Observable

Très peu de changements ici, excepté le fait qu’un event est créé, DonneesMeteoEvent, et qu’il prend en paramètre $this.

Très important, au moment où les mesures sont mises à jour, le dispatcher de Symfony2 est appelé et dispatch l’événement donnees_meteo.update.

4) Nos observers listeners:
AffichageConditionsListener,
AffichagePrevisionsListener,
AffichageStatsListener

5) Rattachons nos listeners à l’observable

Nous avons presque fini. A présent, il faut indiquer à nos listeners qu’ils doivent appeler la fonction update à chaque fois que l’événement donnees_meteo.update est dispatché.

Ici, nous indiquons à Symfony  que nous avons trois listeners (avec le tag kernel.event_listener), qui se déclenche à l’événement donnees_meteo.update, et que nous voulons exécuter la méthode update lorsqu’il est dispatché.

6) Notre contrôleur

That’s it. Il n’y a plus qu’à appeler le chef d’orchestre.

Je sette les valeurs nécessaires pour les différents services (affichageStatsListener et affichagePrevisionsListener). Je mets à jour les données, météo… et c’est tout! En le faisant, je dispatche l’événement donnees_meteo.update, et je mets à jour mes listeners.

Et si l’on veut utiliser des subscribers à la place de listeners?

Bonne question! Un point pour le monsieur du fond!

Déjà, les subscribers, qu’est-ce que c’est? Eh bien, c’est la même chose que les listeners, mais il est possible, dans chacun d’eux, de paramétrer plusieurs événements en indiquant à chaque fois la méthode appelée. Et il est même possible d’indiquer un ordre de priorité pour que les fonctions appelées ne se marchent pas sur les pieds.

Ici, voyez comment on déclare les évenements dans la fonction getSubscribedEvents.

Imaginez que j’ai une autre fonction (appelée ici methodeAAppeler2) qui va être appellée lorsque nous dispatcherons l’événement donnees_meteo.update, mais que je veux qu’il soit appelée après la méthode update.
Imaginez également qu’il y a un autre événement (appelons le evenement2) qui va se produire lorsque nous le dispatcherons, et qu’il devra appeler une méthode appelée methodeAAppeler3.

Je ferai simplement ainsi:

Le second chiffre de l’array me permet de dire que update sera appelée en premier.

Personnellement, j’aime bien les subscribers, mais j’utilise les listeners si je dois faire une toute petite application.

Voyons à présent nos deux autre subscribers:

N’oublions pas de déclarer  nos subscribers en tant que services:

Et pour finir, le contrôleur

Il ne va que très peu différent de notre contrôleur précédent:

 

Comme d’habitude, le dépôt github: https://github.com/jpsymfony/dp-observer.git.

Le répertoire correspondant est SfObserverBundle.

Rédigé par

2 comments

    1. Hello, i tu veux faire ça, il faut déclencher des events), qui pourraient publier des messages sur un exchange rabbitMQ. Tu auras une queue qui écoutera les messages correspondant à une routing key, et en js, tu pourras indiquer la notification dans la barre de l’utilisateur. Mieux vaut gérer ça dans un système de file d’attente telle que rabbitMQ plutôt qu’en synchron (pour éviter la surcharge serveur), surtout que ça dépile rapidement

      Du coup, le workflow serait:
      1) une personne publie un message
      2) un event est lancé (avec le dispatch)
      3) un message est publié dans rabbitMQ
      4) un consumer javascript récupère le message et met à jour la vue (https://www.rabbitmq.com/tutorials/tutorial-one-javascript.html)
      5) un consumer Symfony enregistre en base le message envoyé par l’utilisateur (http://blog.vincent-chalamon.fr/implementer-rabbitmq-dans-une-api-symfony-2/). Préfère ce bundle plus récent: https://github.com/php-amqplib/RabbitMqBundle

      Sinon, pour un système de notifications en direct, il me semble que node.js est plus approprié

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *