[Back to Learn Symfony 2]
Dependency Injection is a mechanism to implement the principle of Control Inversion. It involves dynamically create (inject) at runtime the dependencies between the different classes generally based on a description (configuration file). The dependencies between software components are no longer expressed in the code statically but dynamically determined at runtime.
What is dependency injection?
Dependency Injection is a design pattern and not necesarily php or Symfony 2, but Symfony 2 uses this pattern at the core of the framework.
We could define it a a relation type "Uses": one service uses another without having to pass itself as a parameter in the constructor of another class.
In object-oriented programming, particularly with Frameworks, we often have to handle a large number of different object classes. These objects are responsible for providing a feature or a "service". In a typical application, we will have to handle, for example,
This service description:
- A User object, supposed to represent the user logged into the application
- A Session object for managing the user's session
- A Request an object representing the request sent by a web client
- A Response object for the web response that the application will return
- A Log object, to manage logs
- A Mailer object, in order to send emails
- A Router object to handle routing
- etc ...
The need for dependency injection comes from the fact that some of these objects are linked together, or rather "addicted" to each other, on the other hand the objects are divided into decoupled classes.
For example, the service "Mailer" can be used by the service "Log" to save mails that are sent by the application.
The idea of dependency injection is to use a configuration file to auto-generate a class ("container") that contains methods to allow us to access these services, it will contain the initialization of services (via the instantiation of the class that is), and will manage the dependencies of these services (via constructor or calling methods), service configuration, etc. ....
To illustrate this concept, let's see a small example.
Imagine that we have three services:
* Service mailer (responsible for sending mails)
* Service logger (responsible for recording logs)
* Service router (responsible for routing)
The configuration file
With the configuration file we are giving one service access to another service. A tipycal example is the service Mailer that you can write to specifically send emails and you need to inject it into another service so that service can send emails.
The dependencies injector configuration file might look something like this:
* Service 'mailer'
- Uses the class 'Mailer'
- Passes the service 'logger' in its constructor
- Calls method 'initialize' * Service 'logger'
- Uses the class 'Logger' * Service 'router'
- Uses the class 'Router'
- Calls method 'setLogger', passing it the service 'logger' in parameter
The thing is that we can configurate these services the way we want by creating different dependencies injectors that will automatically generate their containers.
So, we need basically three things:
- Services (like Mailer, Logger, Router..) which are decoupled classes,not linked to each other
- A configuration file (it could be an XML file)
- A container (a class that will couple services and their dependences together)
Service container or dependency injection container
A service container is a class that manages the instatiation of services. With symfony the service container does this for you via configuration files.
Inside your Bundle: