Cette application distribuée sous licence LGPL permet la programmation évènementielle en PHP5. Elle permet aussi de simplifier l'installation d'un système de plugins dans vos applications.
Explication rapide :
1. Créer un évènement.
2. Créer des hooks. Ce sont des fonctions qui seront appelées lors du déclenchement des évènements.
3. Déclencher l'évènement.
Il suffit de lire le code source pour comprendre le fonctionnement très simple de l'application.
Source / Exemple :
<?php
/*
- PHP Events Manager
- Version 1.2.1 (26/08/2007)
- Auteur : Psykocrash (SERRAJ Younes)
-
- PHP Events Manager. Programmation évènementielle en PHP5.
- Copyright (C) 2007 SERRAJ Younes - Tous droits réservés.
-
- Licence : http://www.gnu.org/licenses/lgpl.txt
-
- Cette bibliothèque est un logiciel libre ; vous pouvez la redistribuer ou
- la modifier suivant les termes de la Licence Générale Publique Limitée
- GNU telle que publiée par la Free Software Foundation dans la version 2.1
- de la License.
-
- Cette bibliothèque est distribuée dans l?espoir qu?elle sera utile, mais
- SANS AUCUNE GARANTIE : sans même la garantie implicite de
- COMMERCIABILISABILITÉ ou d?ADÉQUATION À UN OBJECTIF PARTICULIER. Consultez
- la Licence Générale Publique Limitée pour plus de détails.
- ** Vous devriez avoir reçu une copie de la Licence Générale Publique Limitée
- avec cette bibliothèque ; si ce n?est pas le cas, écrivez à la :
- Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- MA 02111-1307, USA.
- /
if (!defined('PEM_PHP5_'))
{
define('PEM_PHP5_', true);
class PEM
{
protected static $events_list = array();
public static $safe_mode = false;
/*
- Cette fonction cré un évènement
- sur lequel pourront être placés
- des hooks.
- /
public static function create_event($event_name)
{
$event_exists = self::event_exists($event_name);
if (self::$safe_mode === true && $event_exists === true)
throw new Exception("[Safe Mode] L'évènement ''" . htmlspecialchars($event_name) . "'' existe déjà.");
if (!$event_exists)
self::$events_list[$event_name] = array();
}
/*
- Cette fonction vérifie si un
- d'évènement existe.
-
- Return: true/false.
- /
public static function event_exists($event_name)
{
if (!is_array(self::$events_list)) return false;
if (array_key_exists($event_name, self::$events_list) === true)
return true;
else
return false;
}
/*
- Cette fonction déclanche un évènement.
- /
public static function raise_event($event_name, $params = '')
{
if (!self::event_exists($event_name))
throw new Exception("L'évènement ''" . htmlspecialchars($event_name) . "'' n'existe pas.");
foreach (self::$events_list[$event_name] as $function_name_to_call)
{
if (!function_exists($function_name_to_call))
throw new Exception("La fonction ''" . htmlspecialchars($function_name_to_call) . "'' n'existe pas.");
if (is_array($params))
call_user_func_array($function_name_to_call, $params);
else
call_user_func($function_name_to_call, $params);
}
}
/*
- Cette fonction supprime un évènement
- et tous les hooks liés.
- /
public static function delete_event($event_name)
{
if (!self::event_exists($event_name))
{
if (self::$safe_mode === true)
throw new Exception("[Safe Mode] L'évènement ''" . htmlspecialchars($event_name) . "'' n'existe pas.");
}
else
unset(self::$events_list[$event_name]);
}
/*
- Cette fonction cré un hook sur
- un évènement.
- /
public static function create_hook($event_name, $function_name_to_call)
{
if (!function_exists($function_name_to_call))
throw new Exception("La fonction ''" . htmlspecialchars($function_name_to_call) . "'' n'existe pas.");
if (!self::event_exists($event_name))
throw new Exception("L'évènement ''" . htmlspecialchars($event_name) . "'' n'existe pas.");
$hook_exists = self::hook_exists($event_name, $function_name_to_call);
if (self::$safe_mode === true && $hook_exists === true)
throw new Exception("[Safe Mode] Le hook ''" . htmlspecialchars($event_name) . '->' . htmlspecialchars($function_name_to_call) . "'' existe déjà.");
self::$events_list[$event_name][$function_name_to_call] = $function_name_to_call;
}
/*
- Cette fonction vérifie si un
- hook existe.
-
- Return: true/false.
- /
public static function hook_exists($event_name, $function_name_to_call)
{
if (!self::event_exists($event_name))
throw new Exception("L'évènement ''" . htmlspecialchars($event_name) . "'' n'existe pas.");
if (array_key_exists($function_name_to_call, self::$events_list[$event_name]) === true)
return true;
else
return false;
}
/*
- Cette fonction supprime un hook
- existant.
- /
public static function delete_hook($event_name, $function_name_to_call)
{
if (!self::hook_exists($event_name, $function_name_to_call))
{
if (self::$safe_mode === true)
throw new Exception("Le hook ''" . htmlspecialchars($event_name) . '->' . htmlspecialchars($function_name_to_call) . "'' n'existe pas.");
}
else
unset(self::$events_list[$event_name][$function_name_to_call]);
}
}
}
?>
Conclusion :
J'ai choisis la catégorie Divers parce que je ne sais vraiment pas laquelle choisir.
Si vous avez des idées d'amélioration, n'hésitez pas. Dans son état naissant, cette application remplit déjà pleinement sa fonction, mais on peut toujours la développer ;)
28 août 2007 à 16:24
Bon courage
25 août 2007 à 17:22
Si tu observes attentivement le...observer..Pattern, tu verras que c'est très exactement ce qu'il fait aussi.
Pourquoi les objets? Parce que cela remplace avantageusement tes fonctions : tu peux alors effectuer des actions bien plus complexes.
Tu n'as pas modifié tes comparaisons : tu devrais les typer. Outre que c'est plus rapide (mais bon, vu l'ordre de grandeur...) c'est surtout plus strict et correct. true et 1 sont identiques. Alors que === true est très différent de === 1. Cela peut avoir son importance, et dans ce sens, il est mieux de prendre l'habitude de coder ainsi.
Coté code encore, vu comment tu as codé ta classe et comment tu dois l'utiliser, tu aurais dû la rendre entièrement statique : toutes les propriétés, et toutes les méthodes. Il est totalement inutile d'instancier ta classe pour l'utiliser. A dire vrai, puisque tu veux ne pas l'utiliser dans un contexte très orienté POO, c'est même bien mieux de ne pas l'instancier.
25 août 2007 à 16:40
Reprenons :
Les évènements ici ne dépendent pas d'un changement d'état comme le voudrait l'Observer design pattern, un évènement peux intervenir n'importe quand, n'importe où, et sans raison. Dans ces conditions, difficile d'associer un sujet, ainsi que ses états, à un observateur précis. Moi je veux bien utiliser ce design pattern, mais faudra m'expliquer comment faire dans cette configuration...
Sinon tu as parlé à plusieurs reprises de passer en paramètre des objets plutôt que des fonctions. Vu que le but est d'appeler des fonctions, je comprend pas pourquoi utiliser des objets ?
25 août 2007 à 16:21
- utiliser un objet complexe comme "hook"
- de déclencher plusieurs actions en cascade : ce n'est pas tout à fait ce que tu as compris. Un évènement entraîne X actions. C'est possible avec ta classe mais pas simplement, et tu n'as aucune interaction possible avec ton environnement. Réagir à un changement est intéressant sans que tu aies à appeler MANUELLEMENT ta fonction. Ta classe ne fonctionne pas comme un trigger. Ou du moins, encore une fois, pas facilement.
Pour la SPL, à jouer avec les itérateurs. Ton objet gagnerait à étendre ArrayIterator, si tu veux que je sois précis. Ou alors, une autre solution est celle que j'ai utilisée : ton event_list doit être un SPLObjectStorage, ce qui t'évite de définir tes méthodes create_event() et compagnie.
Mais bon..ce que j'en dis, moi :-)
25 août 2007 à 13:36
Je me suis renseigné à propos du design pattern Observer, et ce n'est pas du tout ce que je cherche à faire. De ce que j'ai compris, il y a les sujets, et les observateurs, mais tout ça se passe à l'intérieur d'un objet. Mon objectif avec mon application/méthode c'est de pouvoir placer des évènements partout dans mon code (dans la partie "globale"), pas de gérer des évènements au sein d'un objet.
Pour la SPL, j'ai jeté un oeil sur php.net, mais je t'avoue ne pas voir en quoi elle m'aiderait.
Pour le fait d'être limité à une seule fonction, si j'ai bien compris ce que tu voulais dire, et bien non. Pour chaque évènement, tu peux placer autant de hooks que tu le souhaites (hook ici = fonction à appeler). D'ailleurs j'ai une petite idée d'amélioration à ce sujet que je vais implémenter dans la prochaine version.
Pour les exceptions, tu as raison, je vais faire une mise à jour tout de suite.
D'autres remarques/suggestions ?
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.