di icon indicating copy to clipboard operation
di copied to clipboard

DI Extensions can not use parameters from app main configuration

Open forgie1 opened this issue 1 year ago • 8 comments

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);
...

forgie1 avatar Feb 09 '24 16:02 forgie1

Prior version 3.2.0 this actually worked. Will it be working again, or shall we solve it different way?

forgie1 avatar Feb 11 '24 17:02 forgie1

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.

dg avatar Feb 12 '24 18:02 dg

Thank you, this way it is working again.

forgie1 avatar Feb 15 '24 12:02 forgie1

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?

forgie1 avatar Feb 17 '24 13:02 forgie1

@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?

forgie1 avatar Mar 04 '24 17:03 forgie1

Look, I think your use case is very unusual, so it's definitely better if you solve it yourself.

dg avatar Mar 06 '24 10:03 dg

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 @serviceName in 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.

forgie1 avatar Apr 04 '24 17:04 forgie1

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.

forgie1 avatar Apr 04 '24 20:04 forgie1