di
di copied to clipboard
DI Extensions can not use parameters from app main configuration
Version: 3.2.0
Bug Description
config/common.neon
parameters:
secretDir: 'mySecretDir'
extensions:
myDiExtension: Plugin\DIExtension
DIExtension class
...
class DIExtension extends CompilerExtension
{
public function loadConfiguration()
{
$this->compiler->loadConfig(__DIR__ . '/di.neon');
}
}
di.neon
services:
- Plugin\MyService(%secretDir%)
Parameter secretDir is not exchanged (translated) with its value mySecretDir
Expected Behavior
Parameter secretDir will be "translated" to its value mySecretDir
Possible Solution
Load configs in \Nette\DI\Compiler::processExtensions() before running this $first extensions:
$first = $this->getExtensions(Extensions\ParametersExtension::class) + $this->getExtensions(Extensions\ExtensionsExtension::class);
...
Prior version 3.2.0 this actually worked. Will it be working again, or shall we solve it different way?
In this case, the loadDefinitionsFromConfig() method should be used rather than loadConfig(). There was also a problem with expanding parameters, but it's fixed in 3.2-dev
class DIExtension extends CompilerExtension
{
public function loadConfiguration()
{
$config = $this->loadFromFile(__DIR__ . '/di.neon');
$this->loadDefinitionsFromConfig($config['services']);
}
}
Before version 3.2.0 it expanded parameters only inside services but not anywhere else, now it is consistent.
Thank you, this way it is working again.
What is not working this way is:
config file in the main app
services:
service.def:
factory: FQNofService
DI Extension config file loaded via ... $this->loadDefinitionsFromConfig($config['services']);
services:
service.def:
setup:
- register(FQN1())
- register(FQN2())
result is:
Nette\DI\ServiceCreationException
Service 'service.def': Factory and type are missing in definition of service.
This was also working prior 3.2.0 using
...
public function loadConfiguration()
{
$this->compiler->loadConfig(__DIR__ . '/di.neon');
}
In 3.2.0 it is not expanding parameters if $this->compiler->loadConfig() is used or above mentioned Exception is thrown if $this->loadDefinitionsFromConfig($config['services']); is used.
What is the proper way, how to load DI Extension's config.neon file, incl. expanding parameters of services and preventing this DI\Exception to be thrown in v3.2.0?
@dg shall we wait for any update on this issue, or shall we achieve functionality of adding setup: to services from the main App in the DI Extension .neon files another way (our own) -- not using any of Nette methods $this->compiler->loadConfig() || $this->loadDefinitionsFromConfig($config['services']); in the DI Extension?
Look, I think your use case is very unusual, so it's definitely better if you solve it yourself.
OK, I tried it, but it looks the problem is broader. One must choose:
- to use
$this->compiler->loadConfig()---> parameters will not be expanded - or to use
$this->loadDefinitionsFromConfig($config['services']);--> named services loaded this way are not recognized at all using@serviceNamein any other .neon file
I mean this:
.neon file in DI Extension
services:
- Plugin\MyService1(%parameterToBeExpanded%)
myService2:
factory: Plugin\MyService2
.neon file is loaded via $this->loadDefinitionsFromConfig() in the DIExtension so parameters are expanded.
.neon file in the main app
services:
someService:
factory: ServiceFQN
setup:
- attach(@myService2)
The result is Nette\DI\ServiceCreationException: Reference to missing service 'myService2'
So basically all services must be registered in the main App .neon files, not in .neon files of DIExtension package, only then:
- %parameters% will be expanded
- @serviceNames will be possible to use in .neon files
It doesn't look flexible to me -- to use DIExtension is quite complicated this way, if only one of services in the .neon file needs its parameter to be expanded and @serviceName is used in other neon file. It is forcing us to move all services to main app .neon files, or to avoid using %parameters% in DIE, or to use other workaround.
If $this->compiler->loadConfig() would also expand parameters used in services, all the problems mentioned above would be solved and call of $this->loadDefinitionsFromConfig() would not be needed.