[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