0

I have a problem with Events in Symfony. I do not understand how way it works. This is my Listener:

class ClientVisitedListener implements EventSubscriberInterface
{

public static function getSubscribedEvents()
{
    return
    [
        KernelEvents::REQUEST  => 'sprawdz',
    ];
}

My service.yml

anderos_invoice.invoice_club_listener:
class: Anderos\AcpPriceBundle\EventListener\InvoiceClubListener
arguments: [@service_container]
tags:
    - { name: kernel.event_subscriber } 

In all system, I have not any dispatcher. How does it work? Where is the start of this procedure? Maybe in Kernel? Could you help me to understand that procedure?

Ruben Lech
  • 125
  • 12

2 Answers2

3

This is the key to understand what's happening here:

tags:
    - { name: kernel.event_subscriber }  

When the container is being compiled, it uses compiler passes. Compiler pass is an object which, at the time of compilation, gets ContainerBuilder as an argument and can do something with it. For example iterate over all services, check if they have a tag (kernel.event_subscriber in this case) and if so, do something with it.

In this case there is such compiler pass which takes all services having kernel.event_subscriber tag and adds them into EventDispatcher, which already exists in Symfony core (so yes, you have an event dispatcher, although you may not know about it).

That's how it knows which services need to be called when an event occurs - when it happens, the EventDispatcher instance already has registered all listeners/subscribers and simply call them.

Jakub Matczak
  • 15,341
  • 5
  • 46
  • 64
1

When an event happens, then listener that is subscribed to this event will execute some code. Here is how I implemented it.

my service.yml:

app.listener.bot.logger:
    class: AppBundle\Listener\BotLoggerListener
    arguments: ['@logger']
    tags:
        - { name: monolog.logger, channel: bot }
         - { name: kernel.event_listener, event: bot.log.message, method: 'onBotMessage' }

in my controller:

    $event = new BotLogMessage('Request finish ');
    $this->get('event_dispatcher')->dispatch($event::NAME, $event);

the listener:

namespace AppBundle\Listener;
use AppBundle\Event\BotLogRequestEvent;
use AppBundle\Event\BotLogResponseEvent;
use AppBundle\Event\BotLogMessage;
use Psr\Log\LoggerInterface;
class BotLoggerListener
{
    private $logger;
    /**
    * BotLoggerListener constructor.
    * @param LoggerInterface $logger
    */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
    * @param BotLogMessage $event
    */
    public function onBotMessage(BotLogMessage $event)
    {
        $this->logger->info('[Log Message] : ' . $event->getMessage());
    }
}

the event class:

namespace AppBundle\Event;
use AppBundle\Model\BotRequest\BotRequestInterface;
use Symfony\Component\EventDispatcher\Event;
class BotLogMessage extends Event
{
    const NAME = 'bot.log.message';
    /**
     * @var string
     */
    private $message;

    /**
     * @param string $message
     */
    public function __construct($message)
    {
        $this->message = $message;
}

    /**
     * @return string
     */
    public function getMessage() : string
    {
        return $this->message;
    }
}