SmallEventsBundle
Contents
Target
SmallEventsBundle is a symfony bundle to share events accross symfony apps
Concept
We have 3 symfony apps :
- ElasticIndexingApp
- MailApp
- OrderApp
The OrderApp validate an order. When it's done, an event is emmited.
The ElasticIndexingApp receive the event and reindex disponibility of products.
The MailApp want to notify customer the his order is validated. Then, he handle the event and send the mail.
Here is a small scheme to explain the process :
Repository
The source code is available on githut : https://github.com/sebk69/SebkSmallEventsBundle
Installation
This bundle require :
- Php >= 7.0
- Php extensions : bcmath, sockets
- An installation of Symfony 5
- composer
In order to send messages, you'll need a RabbitMQ server. Get it at https://www.rabbitmq.com or, if you use docker, at https://hub.docker.com/_/rabbitmq/.
At the root of your symfony project, type :
composer require sebk/small-events-bundle dev-master
Register bundle in config/bundles.php :
<?php return [ Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true], Sebk\SmallEventsBundle\SebkSmallEventsBundle::class => ['all' => true], ];
Configuration
Create a file config/packages/small-events.yml :
sebk_small_events_bundle: application_id: tuto-1 rabbitmq_server: '%env(RABBITMQ_SERVER)%' rabbitmq_login: '%env(RABBITMQ_LOGIN)%' rabbitmq_password: '%env(RABBITMQ_PASSWORD)%'
As we will see later, the application_id parameter is used to name the rabbitmq queue for events messages. It must be unique in your applications ecosystem.
Emit event
Here is a small example of a command that emit an event each 1 minutes :
<?php namespace App\Command; use Sebk\SmallEventsBundle\Dispatcher\SmallDispatcher; use Sebk\SmallEventsBundle\Event\SmallEvent; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class TestCommand extends Command { protected $dispatcher; public function __construct(SmallDispatcher $dispatcher) { $this->dispatcher = $dispatcher; parent::__construct(); } public function execute(InputInterface $input, OutputInterface $output) { while(true) { $event = new SmallEvent(); $event->setEventName("testEvent"); $event->setData(["id" => 123456]); $this->dispatcher->dispatch($event); sleep(60); } return 0; } }
Subscribe to events
To subscribe to an event, you must create a class in namespace App\EventSubscriber as any symfony event subscriber :
<?php namespace App\EventSubscriber; use Sebk\SmallEventsBundle\Event\SmallEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; class TestSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return [ "testEvent" => "onTestEvent", ]; } public function onTestEvent(SmallEvent $event) { echo $event->getDateEmitted()->format("Y-m-d H:i:s") . " - console 2 - onTestEvent\n"; } }
See "symfony documentation" for more informations
When it's done just use console to handle events from RabbitMq :
$ bin/console sebk:small-events:listen
In production, it is recommended to manage event listeners with process manager like supervisor.