Symfony2 Event Manager: The Stand Alone Way

My first clearer read on event manager on symfony2 was the following.

This article explains how to use the symfony2 even dispatcher to create custom listener and event using the symfony2 event manager component. The blog is very clear and teaches one how to get started on the code for when working inside a symfony2 project.

The second read was this article was a bit old. Actually a year old and taught me a lot about how to work with the stand-alone component however it was kind of unreliable but ultimately very useful. I really liked the examples that they have provided, that helped me to understand how to plug the events, how to work with priorities, how to filter values when working with events, and how use notifyUntil for instance, among other things.

Thirdly, we reviewed the symfony2 documentation chapter titled internal components here.

Basically the model has these components:

The Event is an object subclassed that is passed to all listeners with mechanisms to access information objects regarding the event. “The moral of the story is this: when creating a listener to an event, the Event object that’s passed to the listener may be a special subclass that has additional methods for retrieving information from and responding to the event.”
The Dispatcher class, which is the master class that notifies with the event all the listener classes.
The Listerner class, which is the class who is instructed to listen to the dispatcher events and that can be sub-classed so to extend with some methods to port some objects or data meant to be looked upon or processed/changed. Optionally we can gather all Events into an Events class for documentation purposes and have that class to hold statically the names or strings constants for the event names.

Note: It is important to realize that Dispatcher class is not singleton therefore it has to be injected into my master class from where O use it.
Note: On a last note, there are two approaches for using the event manager: (1) default listener approach, (2) using subscribers.
To stand on the shoulders of dustin10, I asked him what is the difference between these and he answered:

“cordoval they are basically the same thing except a subscriber implemements a method that lets doctrine know which events to subscribe to if using a listener you would create a tag for each event.”

Although I am using it standalone I can get that the idea.

Master Class

This class is in charge of creating all the objects, receive dispatcher injected through DI, assign the listeners on the constructor or elsewhere at initialization. Master class is also in charge of creating the specializing events that give access to some of the objects to compute from/on, and dispatching on a particular event string the corresponding event object just created.

So let’s get to the hands-on part. Let’s try to design this for the tictactoe problem I am facing.

/**
 * Central Class from where dispatcher is used
 */
namespace Tictactoe\Game;
use Symfony\Component\EventDispatcher\EventDispatcher;
class GameMaster
{
    protected $dispatcher = null;
    protected $player = null;
 
    public function __construct(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
 
        $listener = new GameListener();
        $dispatcher->addListener(GameEvents::onFinishPlay, array($listener, 'onFinishPlay'));
 
        $this->player = new Player();
    }
 
    public function play () {       
        $event = new FilterGameEvent($this->player);
        $dispatcher->dispatch(GameEvents::onFinishPlay, $event);
    }
}

Events Class

This class is not mandatory and its only purpose is to hold all the documentation for the strings corresponding to the event channels used in solving the problem. The Events class is mostly used when there are multiple events that need clear documentation. The Events class will allow a developer to easily find the specific event channels the core can dispatch through. This file then becomes very handy for when we need to hack the core, that is extending it, without touching it. We can see this as our list of hooks that we can use to clamp our added functionality to the application.

/**
 * Events Class
 */
namespace Tictactoe\Game;
 
final class GameEvents
{
    /**
     * The event listener receives an Tictactoe\Game\FilterGameEvent
     * instance.
     *
     * @var string
     */
    const onFinishPlay = 'turnswitcher.action';
}

Listener Class

This class should be the keystone in comprising all the logic that should be decoupled from the main core or all the logic that will extend the functionality of the core. Other classes could be easily copy pasted but this one. This class is very customized. The other classes are just copied and adapted to specific problem, they are support classes, whereas the Listener class is the main class that will extend the functionality.

/**
 * Listener TurnSwitcher Class
 */
namespace Tictactoe\Game;
 
use Symfony\Component\EventDispatcher\Event;
 
class TurnSwitcherListener
{
    // ...
    public function onFinishPlay(GameEvent $event)
    {
        // do something like
        $player = $event->getPlayer();
        // extend here the functionality of the core
        // ...
    }
}

Event Class

This class’ main purpose is to provide access to specific objects or parameters that will be useful to our logic extending the core. This class just customizes the method to get certain objects and thereby can be adapted anytime to provide first hand access to the objects that are being read from the master class or that are being written onto the master class set of properties.

/**
 * FilterGameEvent class
 * allows access to the player object
 */
namespace Tictactoe\Game\Event;
 
use Symfony\Component\EventDispatcher\Event;
use Tictactoe\Game\Player;
 
class FilterGameEvent extends Event
{
    protected $player;
 
    public function __construct(Player $player)
    {
        $this->player = $player;
    }
 
    public function getPlayer()
    {
        return $this->player;
    }
}

I hope this makes clearer the Event Manager Pattern as used in symfony2. I will be updating this to correct some mistakes I have made and also I will apply the pattern to the tictactoe game and provide more details on how to install the symfony2 component to be used standalone. So far we have worked on making things understandable.

2 thoughts on “Symfony2 Event Manager: The Stand Alone Way

  1. Pingback: » Event Manager Symfony 2 tips, examples

Leave a Reply to gintare Cancel reply

Your email address will not be published. Required fields are marked *