Wednesday, February 3, 2016

Extending Symfony2 services

Have you ever wondered how could you add some extra functionality to existing symfony2 services, like RequestContext or even override some of it's logic? Here's how!


Powerful decorating


One of awesome things about Symfony2 container is that you can decorate services. In my opinion it is really awesome and powerful - you can simply change behavior of literally any component of Symfony, like EventDispatcher of HttpKernel. It's not too good to tweak them on daily basis, but sometimes you hit edge case when this trick is a life saver. In the end it's nothing more than:

  1. Extending class of service you want to alter.
  2. Making changes - adding methods or overriding exisiting ones.
  3. Writing new service definition.
That's it! Let me show you an example. Let's say that we want to do something abstract, for example modify event_dispatcher service. Let's try to modify dispatch() method, so every attempt of dispatching any of events which name start with "foo" will push some info to logger.

Here's original dispatch() method definition (as of Symfony 2.8):


We cannot edit this method in place, so let's create our own class that extends CoontainerAwareEventDispatcher and overrides it:


Now the last part, service definition:


Note that you should not worry about changed service id. Symfony will do the work for you and you will get your modified dispatcher when you try to get event_dispatcher from container.

Of course this is not the only usage of service decorators. You can also use it to, for example, pass some extra services to class you extend, or replace some service definitions. It is also possible to add some public methods, but my suggestion is to do this only when really neccesary - this way you change original vendor's API which can change or lead other developers into confusion.

I hope you found above stuff useful. Happy coding!