Dans ce tutoriel nous allons découvrir comment mettre en place un système d'évènements en PHP en utilisant les interfaces proposées par le PSR. La recommandation repose sur l'utilisation de 2 interfaces

EventInterface

Cette interface permet de représenter un évènement qui sera ensuite émis à la suite d'une opération dans votre application.

namespace Psr\EventManager;

/**
 * Representation of an event
 */
interface EventInterface
{
    /**
     * Get event name
     *
     * @return string
     */
    public function getName();

    /**
     * Get target/context from which event was triggered
     *
     * @return null|string|object
     */
    public function getTarget();

    /**
     * Get parameters passed to the event
     *
     * @return array
     */
    public function getParams();

    /**
     * Get a single parameter by name
     *
     * @param  string $name
     * @return mixed
     */
    public function getParam($name);

    /**
     * Set the event name
     *
     * @param  string $name
     * @return void
     */
    public function setName($name);

    /**
     * Set the event target
     *
     * @param  null|string|object $target
     * @return void
     */
    public function setTarget($target);

    /**
     * Set event parameters
     *
     * @param  array $params
     * @return void
     */
    public function setParams(array $params);

    /**
     * Indicate whether or not to stop propagating this event
     *
     * @param  bool $flag
     */
    public function stopPropagation($flag);

    /**
     * Has this event indicated event propagation should stop?
     *
     * @return bool
     */
    public function isPropagationStopped();
}

L'interface se compose de 3 getters/setters qui permettent respectivement de définir le nom de l'évènement, la cible de l'évènement et les paramètres associés. Les 2 dernières méthodes permettent de persister l'état de propagation et servira lors du déroulement des listeners.

EventManager

Cette interface permet de représenter la classe qui permettra d'attacher des écouteurs aux différents évènements. C'est cette implémentation qui sera injecté dans les classes qui devront émettre un évènement ou enregistrer un écouteur.


namespace Psr\EventManager;

/**
 * Interface for EventManager
 */
interface EventManagerInterface
{
    /**
     * Attaches a listener to an event
     *
     * @param string $event the event to attach too
     * @param callable $callback a callable function
     * @param int $priority the priority at which the $callback executed
     * @return bool true on success false on failure
     */
    public function attach($event, $callback, $priority = 0);

    /**
     * Detaches a listener from an event
     *
     * @param string $event the event to attach too
     * @param callable $callback a callable function
     * @return bool true on success false on failure
     */
    public function detach($event, $callback);

    /**
     * Clear all listeners for a given event
     *
     * @param  string $event
     * @return void
     */
    public function clearListeners($event);

    /**
     * Trigger an event
     *
     * Can accept an EventInterface or will create one if not passed
     *
     * @param  string|EventInterface $event
     * @param  object|string $target
     * @param  array|object $argv
     * @return mixed
     */
    public function trigger($event, $target = null, $argv = array());
}

Une notion de priorité permet de définir l'ordre d'éxécution des listeners. C'est d'ailleurs lors de l'éxécution de ces derniers que le callback pourra, si besoin, modifier l'état de la propagation (via la méthode stopPropagation(true)). Si l'évènement répond true lors de l'appel à isPropagationStopped() l'éxécution des listeners suivant doit être stoppée.