sfServiceDefinition – a brief introduction

Fabien has already introduced the symfony service container, and will be shortly releasing a post covering more of it. I was keen to get my hands dirty, so I’ve dived into the code and got a quick example working.

This example is perhaps a bit useless in terms of functionality, but I think it does point out some pretty useful points. First we’ll check out the sfServiceContainer:

In my example, I create an Interface which will represent a Request. The IRequest is very basic, and defines just one method – getParameter().

A really simple implementation of this request is as follows:

The only thing worth noting from this class is that we have a constructor that will print out that it’s being constructed – this gives us the ability to see at which point the Service Container actually constructs our object.

Now we will create a service container, and register our request service with it, instructing it we want to use myRequest as our implementation of IRequest.

In the code above, we include the sfServiceContainerAutoloader which will handle autoloading of any other sfServiceContainer classes. We create a new sfServiceDefinition on line 7 – which not surprisingly allows us to define a service. On line 8 we set the service to be shared. A shared service will only be created once, so acts like a singleton in some ways. If we set this to false, everytime getService() was called for that service, we would get a new instance. One very important thing to take note of here is that we haven’t instanced myRequest at this point.

We will now show a simple class called myAction, who’s constructor expects an object implementing IRequest. Notice that we are coding against an interface here and not an implementation. This allows the possibility of replacing myRequest with any other class that implements the interface. The ability to swap out implementations greatly improves the testability of the code. In this example, when testing the myAction class, we could easily create a mock request which implements IRequest. I will leave an explanation of the improved testability for a later date.

Now here’s the clever part – we will define the ‘action’ service, specifying that we want the ‘request’ service as a constructor argument.

We have used sfServiceReference to tell the service container that when it does create an ‘action’ for us, we will want the ‘request’ service to be injected in the constructor. Again, this hasn’t created a myRequest object, or a myAction object yet – only defined them as services.

Below is the script in full:

The output of running this script proves that the Service Container doesn’t create the objects until we actually need them – effectively lazy loading our services.

In a real project, you would define your services, and their dependencies in a configuration file of some sort – either in native PHP, or in XML or YAML.

3 thoughts on “sfServiceDefinition – a brief introduction”

  1. Very cool – I can see the endless flexibility to extend Symfony, something that has been handled well so far, but has certainly had its bounds. Little typo: “that when is does create an ‘action’ for us”, change is=>it

    Great – keep it up, I’ve been looking forward to these articles.

Leave a Reply

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