-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Issue - AbstractDiServiceFactory ,MvcTranslatorFactory throws Exception #5959
Issue - AbstractDiServiceFactory ,MvcTranslatorFactory throws Exception #5959
Conversation
…e interface to an actual instantiable class is up to the user, but now it is possible to request an instance of an interface if the correct instantiator has been defined in Di definition configuration
@@ -18,7 +20,7 @@ class TranslatorServiceFactoryTest extends TestCase | |||
public function setUp() | |||
{ | |||
$this->factory = new TranslatorServiceFactory(); | |||
$this->services = new ServiceManager(); | |||
$this->services = new ServiceManager(new ServiceManagerConfig()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be only relative to the specific test, and not be changed in the setUp
method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ocramius
Thanks.
@noopable I'd actually argue that if you use DI, this should be a DI configuration issue. This affects any service fetched via interface, and you should probably provide either an alias to a concrete instance, or provide an instantiator for this interface. |
@Ocramius In this PR, TranslatorFactory checks the ServiceLocator to have 'Zend\I18n\Translator\TranslatorInterface' . And if we have used any manager of AbstractPluginManagerFactory, DiAbstractServiceFactory is injected to the ServiceLocator. I use the Di for the Domain Object only. |
I have instantiators for services referenced by interface. That's actually how you are supposed to wire together your dependencies (via interface). I agree on being able to discover if a type is actually instantiable via
Right, that is indeed annoying of the Di config, since it will likely break any
No, of course not, but the road is quite bumpy when using Additionally, with this patch, the |
@Ocramius
I agree with you. First, modify AbstractDiServiceFactory::canCreateServiceWithName ex. remove $this->definitions->hasClass but it breaks instantiation from ClassName. Now, Adding Translator configuration with Di is good if we use the Di . Hmmm. |
@noopable a fix would be to "try" instantiating it (hardening the logic at @239f7565e3869f49952c848c2aa52c11a2c13f7e and sacrificing performance - perfectly acceptable though) if ($this->instanceManager->hasSharedInstance($requestedName)
|| $this->instanceManager->hasAlias($requestedName)
|| $this->instanceManager->hasConfig($requestedName)
|| $this->instanceManager->hasTypePreferences($requestedName)
) {
return true;
}
if (! $this->definitions->hasClass($requestedName)) {
return false;
}
try {
$this->get($requestedName);
} catch (DiException $e) {
return false;
}
return true; |
#issuecomment-37542937 This reverts commit 3fe0c9f.
check instantiable strictly
@Ocramius if ($serviceLocator->has('MvcTranslatorAlias')) {
return new MvcTranslator($serviceLocator->get('MvcTranslatorAlias'));
} And anyway, If someone wants to set a Translator instance of MvcTranslator, he can configure the serviceManager to use a key 'MvcTranslator' as the alias or the service instance or override factory configuration of it in module.config.php, doesn't he? |
@noopable using existing class names/interface names is actually a good practice. It is very explicit and less error prone. As for overriding the translator: yes, that indeed can be done, but I think the interface-based service name is there for BC compat. |
Sorry, the last commit fails. (DiAbstractServiceFactoryTest) |
@Ocramius It is good generally to use a namespace driven service name. But I prefer to use symbolic names , because we have some annoying between ServiceManager and RuntimeDefinition. |
@noopable even in the context of I even added a note to the docs last year or so: |
@Ocramius |
@noopable because that's where those "reserved" services actually come from? :-) That's where the entire framework is glued together |
Yes. |
Hey @noopable, I think this PR is actually fine! I'd just want to get the tests for the abstract factory completed, if possible :-) |
@Ocramius I think that interface_exists without typePreference nor alias means "can't create service". if ($this->instanceManager->hasSharedInstance($requestedName)
|| $this->instanceManager->hasAlias($requestedName)
|| $this->instanceManager->hasConfig($requestedName)
|| $this->instanceManager->hasTypePreferences($requestedName)
) {
return true;
}
// sorry updated
if (! $this->definitions->hasClass($requestedName) || interface_exists($requestedName)) {
return false;
} |
@noopable in 99% of cases, the abstract factory is going to be asked to instantiate something via DI right after checking if the service exists. Yes, the side-effect is acceptable, and mitigates the current behavior. |
…eServiceWithName" This reverts commit 7c7d684.
I've applied this on my own project at @Ocramius's suggestion and can confirm it works perfectly. :) |
…ame" This reverts commit 7c7d684.
…teServiceWithName check instantiable strictly
…ctory canCreateServiceWithName" This reverts commit 7c7d684003e1f63b453103f7947ef12492750d52.
…teServiceWithName
…endframework#6022-zendframework/zendframework#6051-di-abstract-factory-without-instantiators-fallback' Close zendframework/zendframework#5959 zendframework/zendframework#6022 zendframework/zendframework#6051
…endframework#6022-zendframework/zendframework#6051-di-abstract-factory-without-instantiators-fallback' into develop Close zendframework/zendframework#5959 zendframework/zendframework#6022 zendframework/zendframework#6051 Forward Port zendframework/zendframework#5959 zendframework/zendframework#6022 zendframework/zendframework#6051
Minimum bootstrap with Di, If Di is enabled, $serviceLocator->get('MvcTranslator'); throws
Zend\Di\Exception\RuntimeException: Invalid instantiator of type "NULL" for "Zend\I18n\Translator\TranslatorInterface".
Relative:
239f756#diff-0683436b236aeed3e48adbdbcfb17914