Dependency Injection (DI)

This feature is part of Extbase 1.3 , included in TYPO3 4.5 LTS .

Setter Injection

Instead of creating objects through t3lib_div::makeInstance (or the new keyword), and connecting them together
manually, you should now use Dependency Injection (DI) for that. N.b. - Dependency Injection is not fully supported in Extbase 1.3 - it will not work for Domain Objects.
Let's give an example: If my class
Tx_Foo_Controller_MyController needs another class Tx_Foo_Service_LoggingService, it can get an instance
of the logging service by Dependency Injection, by specifying the following code:

 1 class Tx_Foo_Controller_MyController {
 2 
 3     /**
 4      * @var Tx_Foo_Service_LoggingService
 5      */
 6     protected $loggingService;
 7 
 8     /**
 9      * @param Tx_Foo_Service_LoggingService $loggingService
10      */
11     public function injectLoggingService(Tx_Foo_Service_LoggingService $loggingService) {
12         $this->loggingService = $loggingService;
13     }
14 }

The DI system finds that the class MyController has an method whose name starts with inject,
and thus passes the logging service to MyController.

Constructor injection

Besides Setter Injection (with inject-methods), Extbase also supports Constructor Injection.
There, the dependencies are set in the constructor arguments, like in the following example:

 1 class Tx_Foo_Controller_MyController {
 2 
 3     /**
 4      * @var Tx_Foo_Service_LoggingService
 5      */
 6     protected $loggingService;
 7 
 8     /**
 9      * @param Tx_Foo_Service_LoggingService $loggingService
10      */
11     public function __construct(Tx_Foo_Service_LoggingService $loggingService) {
12         $this->loggingService = $loggingService;
13     }
14 }

initializeObject() as object lifecycle method

If a method with the name initializeObject() exists, it is called after all dependencies have
been injected and configured; so you can use this method for further initialization work.

Creating Prototype Objects through the Object Manager

To create prototype objects, inject the Object Manager (Tx_Extbase_Object_ObjectManagerInterface),
and use the create() method on the Object Manager, as in the following example.
Do not use t3lib_div::makeInstance anymore!

 1 class Tx_Foo_Controller_MyController {
 2 
 3     /**
 4      * @var Tx_Extbase_Object_ObjectManagerInterface
 5      */
 6     protected $objectManager;
 7 
 8     /**
 9      * @param Tx_Extbase_Object_ObjectManagerInterface $objectManager
10      */
11     public function injectObjectManager(Tx_Extbase_Object_ObjectManagerInterface $objectManager) {
12         $this->objectManager = $objectManager;
13     }
14 
15     public function foo() {
16         $logFile = $this->objectManager->create('Tx_Foo_LogFile');
17     }
18 }

You can also instantiate classes with constructor arguments:

1     public function foo() {
2         $logFile = $this->objectManager->create('Tx_Foo_LogFile', 'arg1', 'arg2');
3     }

You can also inject prototypes into your classes.

Programming against interfaces

In the above example, you have seen that we reference not the concrete implementation ObjectManager,
but instead the ObjectManagerInterface. If a name ends with "...Interface", Extbase DI automatically strips
away the "Interface" from the name, and expects to find a concrete implementation of that interface.
Programming against interfaces is greatly eased by that: For your core classes, you should always reference
an interface, and let the DI container instanciate the concrete class.

Additionally, Extbase DI allows to replace certain implementation classes by other classes through
configuration in TypoScript. Let's give an example, and then you can see the concept:

config.tx_extbase.objects {
    Tx_Extbase_Persistence_Storage_BackendInterface {
        className = Tx_Extbase_Persistence_Storage_Typo3DbBackend
    }
}

This essentially means to the DI container: At all places where the code refers to Tx_Extbase_Persistence_Storage_BackendInterface,
an object of Tx_Extbase_Persistence_Storage_Typo3DbBackend should be instantiated.

This even works with concrete classes - you can configure the DI to replace them.

However, note that this setting can only be configured globally right now, it is not possible to override that on a per-extension basis.

Closing Notes

Dependency Injection does not work yet for Domain Objects which are reconstituted from the database.
With version 1.4 Dependency Injection also works for Domain Objects which are reconstituted from the database.

Generally, the Extbase DI container provides a subset of the functionality of FLOW3's dependency injection.