Symfony2 is a great framework. I use it at OpenSky daily and have contributed a little bit of code to it related to the Doctrine integration.

Symfony2 EventDispatcher

One of the core components is the EventDispatcher and it implements a lightweight version of the Observer design pattern.

At OpenSky we make heavy use of events. All of our core functionality notifies events that we can then listen to and execute other functionality. Here is an example where we notify the user.created event when a new user registers on the site:

$eventDispatcher->notify(new Event($user, 'user.created'));

Now we can setup a listener for that and execute some more PHP code in the same process:

<service id="user.created.listener" class="UserCreatedListener">
    <tag name="kernel.event_listener" event="user.created" method="onUserCreated" />
</service>

The listener class might look something like this:

class UserCreatedListener
{
    public function onUserCreated(EventInterface $event)
    {
        $user = $event->getSubject(); // $user instanceof User
        $params = $event->all();
        // do something
    }
}

The above gets executed in the same process that the user.created event was notified in.

Notifying Asynchronous Events

What if we want to do something else, like notify a third party API of the new user. We shouldn’t do that in the main request as it would slow it down, and it doesn’t need to be real time, so an asynchronous event is perfect.

At OpenSky we make use of HornetQ, a message queue, and a Java application written using Mule to consume messages our PHP application sends. We’ve added a way for Symfony2 events to be forwarded to HornetQ which are then received by our Java app and POSTed back to our PHP application in another request.

Sending an asynchronous event from our PHP app looks like this:

$eventDispatcher->notifyAsync(new Event($user, 'user.created'));

The above would not execute any user.created listeners in this process, instead the Event instance is sent through HornetQ, received by our Java app and POSTed back to our PHP application in another request. The Java app posts to a controller that reconstructs the Event object and notifies it on the event dispatcher.

So this ends up happening but in another request/process:

class EventController
{
    public function handle()
    {
        $event = $this->getEventFactory()->getReconstructedEvent($request);
        $this->getEventDispatcher()->notify($event);
    }
}

Now any code that listens on user.created will be executed in an asynchronous process:

class UserCreatedListener
{
    // ...

    public function onUserCreated(EventInterface $event)
    {
        $user = $event->getSubject(); // $user instanceof User
        $this->someApi->notifyNewUser($user);
    }
}

I don’t have a message queue

In order for you to implement the above example you will need some kind of message queue and middle ware. If you don’t have that you could very easily stash the calls to notifyAsync() and issue the events as async ajax requests when the response renders in the browser or implement some other kind of event persistence and a console command that runs as a daemon constantly processing the events. It is possible to build out a smaller scale version of the example above that is easy to upgrade later.