[TYPO3-mvc] Question about DI and current component wiring method

Bastian Waidelich bastian at typo3.org
Wed Aug 5 11:45:03 CEST 2009


Xavier Perseguers wrote:

Hi Xavier,

> A question arised in my head this morning regarding Dependency Injection 
> and I could not find an answer... I understand it and is described as a 
> way to prevent having explicit dependency on other classes.

Actually it's pretty simple: Instead of instantiating objects within 
your code, you pass them into your object in the constructor or in a 
special setter.

If you look at the tx_fluid viewhelpers we even use it to be able to 
pass in a reference to the tslib_cObj where needed (as a preparation for 
BE use). Only autowiring does not work (yet) in Extbase, so we need a 
fallback in our case:

Tx_Fluid_ViewHelpers_ImageViewHelper

/**
  * @param tslib_cObj $contentObject injector for tslib_cObj (optional)
  * @return void
  */
public function __construct($contentObject = NULL) {
	$this->contentObject = $contentObject !== NULL ? $contentObject : 
$GLOBALS['TSFE']->cObj;
}

As Robert mentioned it's best practice to code against interfaces not 
implementations.
That means, in your code you should have something like:

class MyClass {
	/**
	 * @var Tx_MyExt_LoggerInterface
	 */
	protected $logger;

	public function setLogger(Tx_MyExt_LoggerInterface $logger) {
		$this->logger = $logger;
	}
}

Now you can "inject" your custom logger like:

$myObject = new MyClass();
$myObject->setLogger($myLogger);

And in unit tests you could easily inject a "mock" logger to avoid 
side-effects when testing MyClass.

...But: you still need to instantiate the logger _somewhere_.
In FLOW3 you don't have to care about this most of the time:
When you refer to an interface and there is only one class implementing 
this interface, it would be used automatically.

So you could write:

/**
  * @var \F3\MyPackage\LoggerInterface
  * @inject
  */
protected $logger;

and it would automatically choose the correct implementation.
In the Objects.yaml you can specify which class to instantiate when 
referring to a class name. That's right, you can't only specify the 
implementation, you can even override it.
Thus, if you have

\F3\MyPackage\MyLogger:
   className: \F3\MyOtherPackage\MyOtherLogger

And now, even if you want to create an instance of MyLogger FLOW3s 
object manager will actually create an instance of MyOtherLogger:

$logger = $this->objectManager->getObject('F3\MyPackage\MyLogger');

now $logger would be a MyOtherLogger (assumed that it extends MyLogger)*

And this is where I see a possibilty for Extbase:
I think, it would be great to be able to specify what 
t3lib_div::makeInstance('SomeClass') (or rather 
Tx_Extbase_Object_Manager::getObject()) returns..


Bastian

* Robert, please correct me if I'm wrong ;)


More information about the TYPO3-project-typo3v4mvc mailing list