jf/event

Sistema de eventos PSR-14

2.0.1 2023-07-29 15:50 UTC

This package is auto-updated.

Last update: 2024-04-29 17:27:53 UTC


README

Sistema de eventos PSR-14.

Instalación

Composer

Este proyecto usa como gestor de dependencias Composer el cual puede ser instalado siguiendo las instrucciones especificadas en la documentación oficial del proyecto.

Para instalar el paquete jf/event usando este manejador de paquetes se debe ejecutar:

composer require jf/event

Dependencias

Cuando el proyecto es instalado, adicionalmente se instalan las siguientes dependencias:

PaqueteVersión
psr/event-dispatcher^1.0

Control de versiones

Este proyecto puede ser instalado usando git. Primero se debe clonar el proyecto y luego instalar las dependencias:

git clone git@gitlab.com:joaquinfq/jfEvent.git
cd jfEvent
composer install

Archivos disponibles

Clases

NombreDescripción
jf\event\EventClase simple para eventos genéricos.
jf\event\ManagerManejador simple de eventos.
jf\event\ProxyEvento genérico usado como proxy al objeto almacenado en subject en aquellos caso en los que se quiera pasar al update de los observadores el evento directamente.

Interfaces

NombreDescripción
jf\event\IEventInterfaz para los eventos que se emiten.
jf\event\IObserverInterfaz para los observadores de los eventos.
jf\event\ISubjectInterfaz para los emisores de eventos.

Traits

NombreDescripción
jf\event\TDispatcherTrait que facilita la implementación de las interfaces SplSubject, Psr\EventDispatcher\EventDispatcherInterface y Psr\EventDispatcher\ListenerProviderInterface.
jf\event\TEventTrait para implementar la interfaz IEvent.
jf\event\TEventDispatcherTrait que implementa las interfaces Psr\EventDispatcher\EventDispatcherInterface y Psr\EventDispatcher\ListenerProviderInterface.
jf\event\TObserversGestiona la lista de observadores de los eventos.
jf\event\TSplSubjectTrait que implementa la interfaz SplSubject.
jf\event\TStoppableTrait que implementa la interfaz Psr\EventDispatcher\StoppableEventInterface.

Demos

demos/events.php

Demostración complera del uso de eventos y observadores tanto SPL como jf/event.

<?php

use jf\event\Event;
use jf\event\IObserver;
use jf\event\Manager;
use jf\event\TSplSubject;

require_once __DIR__. '/../vendor/autoload.php';

/**
 * Trait para simplificar la creación de los observadores.
 */
trait TLogObserver
{
    /**
     * @inheritdoc
     */
    public function update(SplSubject $subject) : void
    {
        global $counter;

        if ($subject instanceof LogEvent || $subject instanceof LogEventSplSubject)
        {
            printf("%d %s(%s -- %s)\n", $counter++, static::class, $subject::class, $subject->message);
        }
        else if ($subject instanceof Manager)
        {
            // Se entra aquí si se usa `$manager->notify()`.
            printf("%d %s(%s)\n", $counter++, static::class, $subject::class);
        }
    }
}

/**
 * Evento para registar una traza.
 */
trait TLogEvent
{
    /**
     * Constructor de la clase.
     *
     * @param string $message Mensaje de la traza.
     */
    public function __construct(public readonly string $message)
    {
    }
}

/**
 * Evento para registar una traza.
 */
class LogEvent extends Event
{
    use TLogEvent;
}

/**
 * Evento para registar una traza.
 */
class LogEventSplSubject implements SplSubject
{
    use TLogEvent;
    use TSplSubject;
}

/**
 * Observador para detectar la solicitud de registro de traza y mostrarla por pantalla
 * pero podría almacenarse en disco, base de datos, etc., usando otros observadores.
 *
 * Usando IObserver
 */
readonly class LogObserver implements IObserver
{
    use TLogObserver;

    /**
     * @inheritdoc
     */
    public function observedEvents() : array
    {
        return [ LogEvent::class, LogEventSplSubject::class ];
    }
}

/**
 * Observador para detectar la solicitud de registro de traza y mostrarla por pantalla
 * pero podría almacenarse en disco, base de datos, etc., usando otros observadores.
 *
 * Usando SplObserver
 */
readonly class LogSplObserver implements SplObserver
{
    use TLogObserver;
}

//----------------------------------------------------------------------------------------------------------------------
// Inicio del script
//----------------------------------------------------------------------------------------------------------------------
// Opción 1: Usando el manager y cpm la configuración de eventos y observadores.
//----------------------------------------------------------------------------------------------------------------------
$counter = 1;
$manager = new Manager(
    [
        LogEvent::class           => [ LogObserver::class, LogSplObserver::class ],
        LogEventSplSubject::class => [ LogObserver::class, LogSplObserver::class ]
    ]
);
$manager->dispatch(new LogEvent('Opción 1'));
$manager->dispatch(new LogEventSplSubject('Opción 1'));
$manager->notify(); // No se ha usado `attach` así que no ejecuta ningún observador SPL
//----------------------------------------------------------------------------------------------------------------------
// Resultado por pantalla:
//----------------------------------------------------------------------------------------------------------------------
// 1 LogObserver(LogEvent -- Opción 1)
// 2 LogSplObserver(LogEvent -- Opción 1)
// 3 LogObserver(LogEventSplSubject -- Opción 1)
// 4 LogObserver(LogEventSplSubject -- Opción 1)
// 5 LogSplObserver(LogEventSplSubject -- Opción 1)
// 6 LogObserver(jf\event\Manager)                         <-- notify()
// 7 LogSplObserver(jf\event\Manager)                      <-- notify()
// 8 LogObserver(jf\event\Manager)                         <-- notify()
// 9 LogSplObserver(jf\event\Manager)                      <-- notify()
//----------------------------------------------------------------------------------------------------------------------
// Las lineas 3 y 4 se repiten por pasar el nombre de una clase IEvent y llamarse a observedEvents().
// Al llamar a `notify()` se llamarán a tantos observadores como nombres de clases de observadores se pasaron, en este
// caso 2 para LogEvent y 2 para LogEventSplSubject.
// Si en vez de pasar nombres de clases sino instancias se eliminan algunas de esas duplicidades.
//----------------------------------------------------------------------------------------------------------------------
// Opción 2: Agregando manualmente los eventos y sus observadores.
// Usando `attach` el manager trabaja solamente con IObserver para poder obtener los nombres de los eventos a escuchar.
// El resto debe llamarse con `nofity()`.
//----------------------------------------------------------------------------------------------------------------------
$manager = new Manager();
$manager->attach(new LogObserver());
$manager->attach(new LogSplObserver());                    // No observará eventos al no ser IEvent, se usa con `notify()`
$manager->dispatch(new LogEvent('Opción 2'));
$manager->dispatch(new LogEventSplSubject('Opción 2'));
$manager->notify();                                        // Ejecuta los observadores SPL agregados con attach.
//----------------------------------------------------------------------------------------------------------------------
// Resultado por pantalla:
//----------------------------------------------------------------------------------------------------------------------
// 10 LogObserver(LogEvent -- Opción 2)
// 11 LogObserver(LogEventSplSubject -- Opción 2)
// 12 LogObserver(jf\event\Manager)                        <-- notify()
// 13 LogSplObserver(jf\event\Manager)                     <-- notify()
//----------------------------------------------------------------------------------------------------------------------
// Opción 3: Usando SPL
//----------------------------------------------------------------------------------------------------------------------
$subject = new LogEventSplSubject('Opción 3');
$subject->attach(new LogSplObserver());
$subject->attach(new LogObserver());
$subject->notify();
//----------------------------------------------------------------------------------------------------------------------
// Resultado por pantalla:
//----------------------------------------------------------------------------------------------------------------------
// 14 LogSplObserver(LogEventSplSubject -- Opción 3)
// 15 LogObserver(LogEventSplSubject -- Opción 3)