php uses the Symfony EventDispatcher component

Keywords: Programming

Hello, this article will introduce the use and implementation of Symfony's EventDispatcher component through examples from my actual development work.

This component is very useful in the actual development process. It can make the business logic of the code very clear, increase the reusability of the code, and greatly reduce the code coupling.

brief introduction
Detailed introduction You can view the official documents, below is the document address.

Document Address

Form
A dispatcher object that holds the event name and its corresponding listener
An event with a globally unique event name.Contains some objects that need to be accessed in the subscriber.
Use examples
1. Initialize, add appropriate listening events

# Initially, add listeners
$dispatcher = new EventDispatcher();

$disptacher->addSubscriber(new BIReportSubscriber());   // BI reporting function
$disptacher->addSubscriber(new MediaPlayerSubscriber());  // Maintain Player Information Unification
  1. Symfony\Component\EventDispatcher\EventDispatcher

2. Listened Events

class BIReportSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents ()
    {
    	// Different events listened for, when triggered, the onResponse method is called
        return [
            MusicResponseEvent::NAME => 'onResponse',  
            ChildrenResponseEvent::NAME => 'onResponse',
            FmResponseEvent::NAME => 'onResponse',
            NewsResponseEvent::NAME => 'onResponse',
        ];
    }
    
    public function onResponse(AResponseEvent $event)
    {
    	/*
    	 * Some specific business logic
    	 * Perform BI reporting
    	 */
    }
class MediaPlayerSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents ()
    {
        return [
            MusicResponseEvent::NAME => 'onResponse',
            FmResponseEvent::NAME => 'onResponse',
            ChildrenResponseEvent::NAME => 'onResponse',
            NewsResponseEvent::NAME => 'onResponse',
        ];
    }
    public function onResponse(AResponseEvent $event)
    {
    	/*
    	 * Some specific business logic
    	 * Maintain Player Information Unification
    	 */
    }

Implement the getSubscribedEvents method to complete binding of events.When an event triggers, the dispatcher calls the bound method and passes in the thrown event as a parameter.
The event-bound method onResponse can be any name.
In the onResponse method, get the object to operate on through $event.
3. Event Code
 


class FmResponseEvent extends Event
{
    const NAME = 'fm.response';  // Event Name, Unique Identification of Event

    protected $request;  // Objects to be operated on in the listener

    protected $response;  // Objects to be operated on in the listener

    public function __construct (Request $request, Response $response)
    {
        $this->request = $request;
        $this->response = $response;
    }

    /**
     * @return Request
     */
    public function getRequest()
    {
        return $this->request;
    }

    /**
     * @return Response
     */
    public function getResponse()
    {
        return $this->response;
    }
}
  1. Inherit Symfony\Component\EventDispatcher\Event
  2. The $request and $response objects are required in the subscriber's business logic, so this event contains objects of both classes.

4. Trigger Events

 $event = new FmResponseEvent($request, $response);
 $dispatcher->dispatch($event::NAME, $event);
  1. The dispathcer executes the method of event binding in the subscriber in turn, by priority

Source Code Interpretation

1 Simplified EventDispatcher source

class EventDispatcher implements EventDispatcherInterface
{
    private $listeners = array();
    
    private $sorted = array();
    
    /**
     * Trigger Event
     */
    public function dispatch($eventName, Event $event)
    {
        if ($listeners = $this->getListeners($eventName)) {
            $this->doDispatch($listeners, $eventName, $event);
        }

        return $event;
    }

    /**
     *  Search listeners by event name
     */
    public function getListeners($eventName)
    {
        if (empty($this->listeners[$eventName])) {
            return array();
        }

        if (!isset($this->sorted[$eventName])) {
           $this->sortListeners($eventName);
        }

        return $this->sorted[$eventName];
    }
    
    /**
     * Sort listeners by priority
     * @param string $eventName
     */
    private function sortListeners($eventName)
    {
        krsort($this->listeners[$eventName]);
        $this->sorted[$eventName] = array();

        foreach ($this->listeners[$eventName] as $priority => $listeners) {
            foreach ($listeners as $k => $listener) {
                if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
                    $listener[0] = $listener[0]();
                    $this->listeners[$eventName][$priority][$k] = $listener;
                }
                $this->sorted[$eventName][] = $listener;
            }
        }
    }


    protected function doDispatch($listeners, $eventName, Event $event)
    {
        foreach ($listeners as $listener) {
            if ($event->isPropagationStopped()) {
                break;
            }
            \call_user_func($listener, $event, $eventName, $this);
     }
    
    /**
     * Add Subscriber
     */
    public function addSubscriber(EventSubscriberInterface $subscriber)
    {
        foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
            if (is_string($params)) {
                $this->addListener($eventName, array($subscriber, $params));
            } elseif (is_string($params[0])) {
                $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
            } else {
                foreach ($params as $listener) {
                    $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
                }
            }
        }
    }
    
    public function addListener($eventName, $listener, $priority = 0)
    {
        $this->listeners[$eventName][$priority][] = $listener;
        unset($this->sorted[$eventName]);
    }
}

Buy me a cup of coffee :)

Posted by digitalbart2k on Wed, 18 Dec 2019 22:06:12 -0800