- ^ Composants de jelix
- jTpl : le moteur de templates
- jZone : découper vos pages en zones
- jDao : mapping objet relationnel
- Formulaires classiques
- jForms : des formulaires automatiques
- jDb : accéder à une base de données SQL
- jKvDb : accéder à une base de type key/value
- jUrl : des URLs automatiques
- jAuth : système d'authentification
- jAcl2 : système de droits
- jLocale: internationaliser votre application
- jEvents : communication inter-module
Chapitre: jEvents : communication inter-module
« jLocale: internationaliser votre application | ^ Composants de jelix |
− Table des matières
Jelix propose un système de communication inter-module, basé sur le principe d'événements/écouteurs.
Il est possible d'émettre un événement de n'importe quel endroit dans votre code, et les modules qui "écoutent" cet événement pourront y répondre, et même renvoyer des données. C'est donc en quelque sorte un système de broadcast, avec des clients (les émetteurs) et des serveurs (les listeners).
Il y a donc d'une part un objet jEvent
, permettant d'émettre un événement
et de récupérer les réponses, et d'autre part, des "listeners", qui sont des
classes placées dans les modules, contenant les méthodes "répondant" aux
événements.
Émettre un évènement ¶
L'objet jEvent
sert à la fois d'émetteur d'événement, et en même temps de
conteneur des réponses.
Pour émettre un événement, il faut utiliser la méthode statique notify()
.
Elle accepte en paramètre un nom d'évènement (qui n'est constitué que de caractères alphanumériques), et un tableau facultatif de paramètres (à utiliser selon l'évènement).
Vous recevez en retour l'objet jEvent
instancié pour l'occasion, et
contenant les réponses (ne pas confondre avec les objets jResponse
,
utilisés dans les contrôleurs). Les réponses sont un ensemble de valeurs dont la
structure et le nombre dépend de l'événement et du nombre de modules ayant
répondu.
//exemple avec paramètre
$eventParams = array('user' => $userObject);
$theEvent = jEvent::notify('authCanLogin', $eventParams);
//exemple sans paramètres
$theEvent = jEvent::notify('authCanLogin2');
Pour accéder aux données des réponses retournés par les listeners des modules,
il faut utiliser la méthode getResponse
de l'objet jEvent
qui a été
retourné par notify
:
$reponses = $theEvent->getResponse();
Le résultat est un tableau des données que chaque module à renvoyé.
Vous avez d'autres méthodes pour manipuler les données retournées :
inResponse($responseKey, $value)
: indique si il existe une clé avec la valeur donnée dans les données retournées.getResponseByKey($responseKey)
: renvoi la liste des données qui correspondent à la clé donnée (renvoi null si il n'y a aucune donnée avec cette clé)allResponsesByKeyAreTrue($responseKey)
: indique si toutes les données avec la clé donnée ont la valeur true.allResponsesByKeyAreFalse($responseKey)
: indique si toutes les données avec la clé donnée ont la valeur false.
Répondre à un évènement ¶
Il n'y a pas de listener par défaut dans les modules. Aussi, pour qu'un module
puisse répondre à un événement, il faut en créer un, et le déclarer dans le
fichier events.xml
du module. Il n'y a pas de limite du nombre de
listener.
Il y a deux choses à faire pour un listener : le créer, puis le déclarer.
Créer le listener ¶
Un listener est une classe stockée dans classes
avec un nom spécifique.
Depuis Jelix 1.8.1, cela peut être une classe stockée n'importe où, avec n'importe quel nom, et qui doit être auto-chargeable. Ce qui est beaucoup moins contraignant.
Pour créer un listener dans classes
, il faut d'abord lui donner un nom logique.
Nous allons utiliser "auth" par exemple.
Ensuite il faut créer une classe pour le listener. Son nom est une concatenation
du nom logique avec "Listener". Stocker cette classe dans un fichier qui a pour
nom nomlogique.listener.php
, et donc auth.listener.php
pour notre
exemple, ce fichier devant être dans le dossier classes
du module.
Une classe de listener doit hériter de jEventListener
et doit contenir une
méthode pour chaque évènement auquel le listener
répond. Ces noms de méthodes commencent par on
suivi du nom d'événement. Et
ces méthodes prennent en paramètre l'objet jEvent
correspondant à
l'événement. Exemple :
class authListener extends jEventListener {
// ou
// class \MyModule\Listeners\Auth extends \jEventListener {
function onAuthCanLogin ($event) {
// recupération d'un paramètre de l'événment
$user = $event->getParam('user');
// traitement
$ok = true;
if (isset($user->actif)) {
$ok = ($user->actif == '1');
}
$ok = $ok && ($user->password != '');
// renvoi de donnée en réponse
$event->add(array('canlogin'=>$ok));
}
}
Ce listener répond à l'évènement "AuthCanLogin". La méthode récupère le
paramètre 'user' de l'évènement. Et ajoute une donnée dans la réponse avec la
méthode add
. Ce paramètre et cette donnée de réponse dépendent uniquement
de l'évènement AuthCanLogin. Pour d'autres évènements, il peut y avoir plusieurs
paramètres ou aucun, d'autres types de données de réponses ou aucune réponse.
Pour les évènements dont le nom ne peut correspondre à un nom de méthode,
comme un nom comportant des points (ex: foo.bar
), vous pouvez indiquer
quelle méthode il faut exécuter, dans une propriété eventMapping
. Les clés
sont les noms d'évènements, les valeurs les noms des méthodes.
class authListener extends jEventListener {
protected $eventMapping = array(
'foo.bar' => 'execFooBar'
);
function execFooBar ($event) {
// here process the event.
}
}
Note : vous pouvez changer la façon dont votre listener traite les évènements
(nom des méthodes correspondantes aux évènements etc), en redéfinissant la
méthode performEvent()
du listener.
Déclarer le listener ¶
il faut ensuite déclarer le listener. Cela se fait dans un fichier
events.xml
placé à la racine du module. Voici un exemple :
<events xmlns="http://jelix.org/ns/events/1.0">
<listener name="auth">
<event name="AuthCanLogin" />
</listener>
<!-- or -->
<listener name="\MyModule\Listeners\Auth">
<event name="AuthCanLogin" />
</listener>
</events>
L'attribute name
de la balise listener
doit contenir le nom logique
du listener, si sa classe est stockée dans classes/
, ou le nom
entier de la classe si elle est auto-chargeable.
Vous pouvez déclarer autant de listener que vous voulez grâce à la balise
<listener>
. Et dans chacune d'elles vous indiquez tous les évènements que
prend en charge le listener, grâce à des balises <event>
.
Désactiver des listeners ¶
Il peut arriver que vous vouliez désactiver un listener fourni par un module tiers, pour un tas de raison.
Cela est possible en les indiquant dans la section [disabledListeners]
de la configuration principale. Les clés sont les noms d'évènements, les
valeurs sont les sélecteurs des listeners ou le nom complet de la classe
du sélecteur si elle est autochargeable.
[disabledListeners]
authLogin="aModule~theListener"
Dans cet example, le listener theListener
du module "aModule" ne sera
pas appelé quand l'évènement authLogin
sera émis.
Si vous voulez désactiver plusieurs listener pour un même évènement,
utilisez simplement la notation []
pour indiquer un tableau :
[disabledListeners]
authLogin[]="aModule~theListener"
authLogin[]="\MyModule\Listeners\Auth"