Symfony - Events and EventListener



Symfony provides event-based programming through its EventDispatcher component. Any enterprise application needs event-based programming to create a highly customizable application. Events is one of the main tools for the objects to interact with each other. Without events, an object does not interact efficiently.

The process of event based programming can be summarized as - An object, called Event source asks the central dispatcher object to register an event, say user.registered. One or more objects, called listener asks the central dispatcher object that it wants to listen to a specific event, say user.registered. At some point of time, the Event source object asks the central dispatcher object to dispatch the event, say user.registered along with an Event object with the necessary information. The central dispatcher informs all listener objects about the event, say user.registered and its Event* object.

In event-based programming, we have four types of objects: Event Source, Event Listener, Even Dispatcher, and the Event itself.

Let us write a simple application to understand the concept.

Step 1 − Create a project, event-dispatcher-example.

cd /path/to/dir 
mkdir event-dispatcher-example 
cd event-dispatcher-example 
composer require symfony/event-dispatcher 

Step 2 − Create a class, .User.

class User { 
   public $name; 
   public $age; 
}  

$user = new User(); 
$user->name = "Jon"; 
$user->age = 25

Step 3 − Create an event, UserRegisteredEvent.

use Symfony\Component\EventDispatcher\Event;  
class UserRegisteredEvent extends Event {
   const NAME = 'user.registered';  
   protected $user;  
   
   public function __construct(User $user) { 
      $this-<user = $user; 
   }  
   public function getUser() { 
      return $this-<user; 
   } 
}  
$event = new UserRegisteredEvent($user);

Here, UserRegisteredEvent has access to User object. The name of the event is user.registered.

Step 4 − Create a listener, UserListener.

class UserListener { 
   public function onUserRegistrationAction(Event $event) { 
      $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
         echo $user->age . "\r\n"; 
   } 
}  
$listener = new UserListener(); 

Step 5 − Create an event dispatcher object.

use Symfony\Component\EventDispatcher\EventDispatcher;  
$dispatcher = new EventDispatcher(); 

Step 6 − Connect listener and event using dispatcher object and its method, addListener.

$dispatcher 
   ->addListener( 
      UserRegisteredEvent::NAME,  
      array($listener, 'onUserRegistrationAction'));  

We can also add an anonymous function as event listener as shown in the following code.

$dispatcher 
   ->addListener( 
      UserRegisteredEvent::NAME,  
      
      function(Event $event) { 
         $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
      }); 

Step 7 − Finally, fire / dispatch the event using event dispatcher's method, dispatch.

 $dispatcher->dispatch(UserRegisteredEvent::NAME, $event);

The complete code listing is as follows.

main.php

<?php  
   require __DIR__ . '/vendor/autoload.php';  
   use Symfony\Component\EventDispatcher\EventDispatcher; 
   use Symfony\Component\EventDispatcher\Event;  

   class User { 
      public $name; 
      public $age; 
   }  
   class UserRegisteredEvent extends Event { 
      const NAME = 'user.registered';  
      protected $user;  
      
      public function __construct(User $user) { 
         $this->user = $user; 
      }  
      public function getUser() { 
         return $this->user; 
      } 
   }  
   class UserListener { 
      public function onUserRegistrationAction(Event $event) { 
         $user = $event->getUser(); 
         echo $user->name . "\r\n"; 
         echo $user->age . "\r\n"; 
      } 
   } 
   $user = new User(); 
   $user->name = "Jon"; 
   $user->age = 25;  

   $event = new UserRegisteredEvent($user); 
   $listener = new UserListener();  

   $dispatcher = new EventDispatcher();  
   $dispatcher 
      ->addListener( 
         UserRegisteredEvent::NAME, 
         
         function(Event $event) { 
            $user = $event->getUser(); 
            echo $user->name . "\r\n"; 
         });  
   $dispatcher 
      ->addListener( 
         UserRegisteredEvent::NAME, array($listener, 'onUserRegistrationAction'));

   $dispatcher->dispatch(UserRegisteredEvent::NAME, $event); 
?>

Result

Jon 
Jon 
25

Symfony web framework has a lot of events and one can register listener for those events and program it accordingly. One of the sample event is kernel.exception and the corresponding event is GetResponseForExceptionEvent, which holds the response object (the output of a web request). This is used to catch the exception and modify the response with generic error information instead of showing runtime error to the users.

Advertisements