50 votes

Mise en œuvre des meilleures pratiques en matière d'écoute d'événements en PHP

J'essaie de créer un système de type CMS en PHP, en le rendant aussi modulaire et extensible que possible.

Pourrait-on me proposer un scénario de bonnes pratiques pour créer un système d'écoute d'événements en PHP (une version très simplifiée du système Drupal par exemple), la création de hooks et leur implémentation dans un court exemple serait également appréciable.

1 votes

Ceci pourrait vous intéresser : components.symfony-project.org/event-dispatcher

139voto

ircmaxell Points 74865

Il existe en fait trois façons différentes de procéder du point de vue de l'implémentation (notez qu'il s'agit de modèles de conception OO, mais que vous pourriez les implémenter de manière fonctionnelle ou procédurale si vous le souhaitiez).

1. Modèle d'observateur

Vous pouvez mettre en œuvre le Modèle d'observateur . En gros, chaque chose qui peut susciter des événements serait un sujet. Ensuite, les classes/codes que vous voulez écouter se lient à ce qu'ils veulent écouter spécifiquement. Disons que vous avez un contrôleur appelé Foo . Si vous voulez l'écouter, vous pouvez téléphoner à $fooController->attach($observer); . Ensuite, lorsque le contrôleur veut dire quelque chose, il envoie l'événement à tous les observateurs.

Cela convient parfaitement à un système de notification (pour étendre ce que font les classes). Il n'est pas aussi bien adapté pour modifier le comportement du code en temps réel.

2. Motif décoratif Vous pouvez également mettre en œuvre la fonction Motif décoratif . En fait, vous prenez l'objet que vous voulez modifier et vous l'"enveloppez" dans un nouvel objet qui fait ce que vous voulez changer. Cette méthode convient parfaitement à la modification et à l'extension du comportement (puisque vous pouvez remplacer de manière sélective les fonctionnalités de la classe enveloppée).

Cela fonctionne très bien si vous avez défini des interfaces et que vous attendez des objets qu'ils s'y conforment. Si vous n'avez pas d'interfaces (ou si vous ne les utilisez pas correctement), la plupart des possibilités offertes par le décorateur seront perdues.

Notez également qu'il ne s'agit pas vraiment d'une façon de faire des événements, mais d'une façon de modifier le comportement d'un objet.

3. Modèle de médiateur

Vous pouvez également utiliser un Médiateur . En fait, vous auriez un médiateur global qui garderait la trace de vos auditeurs. Lorsque vous souhaitez déclencher un événement, vous envoyez l'événement au médiateur. Le médiateur peut alors garder la trace des objets d'écoute qui souhaitent recevoir cet événement et transmettre le message de manière appropriée.

Il a l'avantage d'être central. Cela signifie que plusieurs expéditeurs peuvent envoyer le même événement, sans que les auditeurs ne fassent de différence quant à l'identité de l'expéditeur...

J'ai développé ce sujet dans un article de blog.

3 votes

Pour une mise en œuvre réelle à explorer, WordPress met en œuvre le modèle de l'observateur en utilisant add_action et quelques autres choses. Ce n'est pas très beau, mais ça a tendance à fonctionner.

5 votes

@Casey : C'est le modèle du médiateur, pas celui de l'observateur. Chaque fois que vous ne vous attachez pas à la chose que vous voulez écouter directement, il s'agit d'un modèle de médiateur. Mais c'est un exemple d'implémentation procédurale d'un modèle de conception OO... C'est donc un commentaire très utile...

1 votes

@ircmaxwell - Merci pour cet éclaircissement, très apprécié.

35voto

Erwinus Points 1587
/*
 Example 1: 
 event::bind('blog.post.create', function($args = array())
 {
    mail('myself@me.com', 'Blog Post Published', $args['name'] . ' has been published');
});

 Example 2: 
 event::trigger('blog.post.create', $postInfo);
*/

class event
{
    public static $events = array();

    public static function trigger($event, $args = array())
    {
        if(isset(self::$events[$event]))
        {
            foreach(self::$events[$event] as $func)
            {
                call_user_func($func, $args);
            }
        }

    }

    public static function bind($event, Closure $func)
    {
        self::$events[$event][] = $func;
    }
}

2 votes

Simple et efficace. Certains utilisateurs préféreront peut-être call_user_func_array pour décomposer les $args en variables passées individuellement au lieu d'un tableau comme seul paramètre. Merci Erwinus.

2 votes

Je sais que vous demandez un objet de clôture, mais pourquoi ? Vous pourriez aussi faire référence à une méthode de classe qui n'est pas anonyme. Peut-être voulez-vous aussi appeler une fonction/méthode normale.

0 votes

@user3292653 : Si vous n'êtes pas d'accord, changez le si vous voulez, la source est libre ;-)

13voto

user187291 Points 28951

Voici comment j'ai procédé pour quelques projets

Tous les objets sont créés à l'aide d'une fonction de construction au lieu de new de l'opérateur.

 $obj = _new('SomeClass', $x, $y); // instead of $obj = new SomeClass($x, $y);

Cette méthode présente de nombreux avantages par rapport à la méthode brute. new Du point de vue de la gestion des événements, il est important que le système _new() gère une liste de tous les objets créés.

Il existe également une fonction globale send($message, $params) qui parcourt cette liste et, si un objet expose une méthode "on_$message", appelle cette méthode en lui transmettant des paramètres :

function send() {
    $_ = func_get_args();
    $m = "on_" . array_shift($_);
    foreach($_all_objects as $obj)
        if(method_exists($obj, $m))
            call_user_func_array(array($obj, $m), $_);
}

Ainsi, par exemple, send('load') appellera on_load pour chaque objet qui l'a définie.

0 votes

Wow... une façon très intelligente de procéder !

4voto

scoates Points 658

Si vous utilisez PHP 5.3 (et avez donc accès à des fermetures riches), le système d'événements/filtres en Lithium est ce que j'utiliserais comme base pour les AOP en PHP.

0 votes

-1 car cela ne répond pas vraiment à la question de savoir COMMENT créer une bibliothèque d'écouteurs d'événements. Cela aurait dû être un commentaire.

5 votes

+1 car Lithium est un excellent exemple de la façon de faire de l'événementiel et de l'écoute. C'est un peu difficile à comprendre la première fois, mais c'est extrêmement puissant : Un article utile à ce sujet , Source .

0 votes

En combinant l'inspiration de Lithium avec les filtres de flux, la réflexion sur les jetons, les décorateurs, les raccourcis et les fermetures de PHP5.4 en un seul endroit, on obtient un véritable framework AOP : Allez-y ! AOP PHP , fuente

-4voto

user3225313 Points 9

Je ne comprends pas très bien pourquoi les gens de PHP pensent qu'ils gagnent quelque chose avec les auditeurs. Question simple : Si je cherche des développeurs PHP, je pose simplement une question : quels sont les problèmes et les limites de MVC ?

Si vous ne pouvez pas répondre à cette question, vous ne devriez pas envisager de mettre en œuvre des auditeurs, ni d'ailleurs de mettre en œuvre un cadre.

Suivant Connaître sa langue. PHP est single thread, single build. Cela signifie que la mémoire et les objets sont spécifiques à chaque thread. Par conséquent, les listeners et autres objets de Java/C# ne devraient jamais être utilisés en PHP, car ils ont tendance à être coûteux à construire et à compliquer l'application sans apporter suffisamment de valeur ajoutée pour les justifier.

Les Frameworks ne sont PAS supportés, et il y a 2 ans, le responsable de PHP a déclaré qu'il n'avait pas l'intention de supporter les Frameworks pour PHP. Cela signifie que pour qu'un framework fonctionne à moitié aussi bien que le PHP natif avec PEAR, vous devez implémenter des douzaines de compléments qui prennent de la mémoire, compliquent le développement et obscurcissent le code sans aucun avantage.

Le développement PHP standard est plus rapide et plus facile à utiliser que la plupart des frameworks pour PHP. Il existe plusieurs bibliothèques PEAR qui peuvent vous aider grandement dans votre tâche. N'essayez pas d'être un développeur multithread sur un système à un seul thread, le serveur n'a pas de valeur réelle.

Si vous avez besoin d'une communication inter-filière, abandonnez PHP et développez dans un langage multi-filière.

N'utilisez pas la technologie à cause d'un mot "BUZZ". La technologie MVC est utilisée à outrance et, dans 99 % des cas, mal utilisée. Le résultat va de la lenteur des systèmes à la médiocrité des structures de données et de la validation. Les auditeurs sont les mêmes, il faut savoir ce que c'est avant de l'utiliser.

La première question qui se pose est la suivante : comment faire ? devrait être pourquoi ? Connaissez votre technologie, les tendances engendrent de mauvaises habitudes et des développeurs médiocres.

Désolé, la boîte à savon est terminée, j'en ai juste assez de rencontrer des développeurs PHP ordinaires qui répètent comme des perroquets des réponses et des idéologies sans y réfléchir. C'est pourquoi les développeurs Java se moquent des développeurs PHP, parce qu'ils essaient d'utiliser une technologie pour laquelle leur langage n'a pas été conçu, et que le créateur a dit qu'il n'avait pas l'intention de supporter.

Il y a d'excellents développeurs PHP, mais pas ceux qui essaient d'utiliser des frameworks étroits comme Zend Framework, ou des technologies comme Domain Controllers ou Listeners.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X