# Event dispatcher

## Event dispatcher

**Events and Event Listeners**

* Creating an event listener

  ```php
  // src/EventListener/ExceptionListener.php
  namespace App\EventListener;

  class ExceptionListener
  {
      public function __invoke(ExceptionEvent $event): void // this event listener listens to Excepction events
      {
          // You get the exception object from the received event
          $exception = $event->getThrowable();

  				// ...

          // sends the modified response object to the event
          $event->setResponse($response);
      }
  }
  ```

  ```yaml
  # config/services.yaml
  services:
    App\EventListener\ExceptionListener: # register the class and tell symfony that is an event listener 
        tags: [kernel.event_listener] # or { name: kernel.event_listener, event: kernel.exception (if not typ), method: methodName }
  ```

  Using php attributes

  ```php
  namespace App\EventListener;

  use Symfony\Component\EventDispatcher\Attribute\AsEventListener;

  #[AsEventListener(event: CustomEvent::class, method: 'onCustomEvent')]
  #[AsEventListener(event: 'foo', priority: 42)]
  #[AsEventListener(event: 'bar', method: 'onBarEvent')]
  final class MyMultiListener
  {
      public function onCustomEvent(CustomEvent $event): void
      {
          // ...
      }

      public function onFoo(): void
      {
          // ...
      }

      public function onBarEvent(): void
      {
          // ...
      }

      #[AsEventListener(event: 'bar')]
      public function onBarEvent(): void
      {
          // ...
      }
  }
  ```
* Creating an Event Subscriber

Event Subscriber: Class that defines one or more methods that listen to on or various events. Self-contained, doesn’t need yaml config

```php
// src/EventSubscriber/ExceptionSubscriber.php
namespace App\EventSubscriber;

class ExceptionSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::EXCEPTION => [
                ['processException', 10],
                ['logException', 0],
                ['notifyException', -10],
            ],
        ];
    }

    public function processException(ExceptionEvent $event): void
    {
        // ...
    }

    public function logException(ExceptionEvent $event): void
    {
        // ...
    }

    public function notifyException(ExceptionEvent $event): void
    {
        // ...
    }
}
```

* Dispatch custom event

Event

```php
// src/Event/AfterSendMailEvent.php
namespace App\Event;

use Symfony\Contracts\EventDispatcher\Event;

class AfterSendMailEvent extends Event
{
    public function __construct(
        private mixed $returnValue,
    ) {
    }

    public function getReturnValue(): mixed
    {
        return $this->returnValue;
    }

    public function setReturnValue(mixed $returnValue): void
    {
        $this->returnValue = $returnValue;
    }
}
```

Subscriber

```php
// src/EventSubscriber/MailPostSendSubscriber.php
namespace App\EventSubscriber;

use App\Event\AfterSendMailEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class MailPostSendSubscriber implements EventSubscriberInterface
{
    public function onMailerPostSend(AfterSendMailEvent $event): void
    {
        $returnValue = $event->getReturnValue();
        // modify the original $returnValue value

        $event->setReturnValue($returnValue);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            'mailer.post_send' => 'onMailerPostSend',
        ];
    }
}
```

1. **Observer Pattern**:
   * **Purpose**: The Observer pattern is a software design pattern where an object (known as the subject) maintains a list of its dependents (observers) and notifies them automatically of any state changes, usually by calling one of their methods.
   * **In Symfony**: In the context of Symfony's EventDispatcher, the events are the "subjects," and the event listeners or subscribers are the "observers". When an event is dispatched, the EventDispatcher notifies all registered listeners for that event, thus "observing" the event.
   * **Benefits**: This pattern promotes loose coupling, as the subject doesn't need to know anything about the observers beyond the fact that they implement a certain interface. This allows for very dynamic behavior, as observers can be added, removed, or changed at runtime.
2. **Mediator Pattern**:
   * **Purpose**: The Mediator pattern is used to reduce chaos among interconnected components in a system by encapsulating the way these components interact. It promotes the principle that "objects don't call each other directly but instead go through a mediator."
   * **In Symfony**: The **`EventDispatcher`** acts as a mediator in the sense that it's the object through which events (messages) pass. The components dispatching events and the listeners responding to them don't interact directly. They connect through the dispatcher, which handles the routing of events to the appropriate listeners.
   * **Benefits**: This central point of control allows for more controlled, maintainable interactions between objects. It also makes your system easier to understand, change, and extend.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://senens-organization.gitbook.io/senenhermida.docs/symfony/event-dispatcher.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
