-
-
Notifications
You must be signed in to change notification settings - Fork 312
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add parameters to the DecoratorResolver callable call #801
Comments
Can you show a code example that isn't working right now, and that would work with your suggestion? That will help understand. |
# We define env parameters in some core definition, let's assume we use "core library" in a several microservices,
# and we want to put this core definitions into the library.
# What I want to achieve is an analogue of symfony EnvVarProcessor,
# and benefit from container compilation in the meantime.
class CoreParametersDefinitions extends DefinitionArray {
public function __construct() {
# Environment "HOSTS_LIST=host1,host2" is a list of a hosts
# but this could be any other primitive like boolean or double, or it could be a json string
# So we could have different processors
parent::__construct( [ 'env(csv:HOSTS_LIST)' => env('HOSTS_LIST')]);
}
}
class EnvVarProcessorDefinitions extends DefinitionArray {
public function __construct() {
parent::__construct(
[
# We can add any processor we want. So this 'csv' processor here will process env(csv:HOSTS_LIST)
EnvVarProcessorFactory::class => autowire()
->method('addProcessor', 'csv', get(CSVEnvVarProcessor::class))
]
);
}
}
# This is a part of a "core library" - we decorate definitions before container is compiled.
class DecoratedDefinitions extends DefinitionArray {
public function __construct(DefinitionSource $previousDefinitions) {
$normalizedEnvDefinitions = [];
foreach ($previousDefinitions->getDefinitions() as $key => $definition) {
if (strpos($key, 'env(') === 0 && strpos($key, ':') > 0) {
preg_match('/^env\(([^:]+):/', $key, $matches);
#Does not use "static"/"self"/"$this" or "use" keywords, and could be compiled.
$compilableClosure = function ($value, ContainerInterface $container, array $params) {
#The issue is here - currently we have only value in the closure, and params are empty,
# but it would be nice to have params here
return $container->get(EnvVarProcessorFactory::class)->getProcessor($params['type'])->process($value);
};
# decorate and pass the parameters to the helper.
# Currently the values we pass to the 'parameter()' method also are passed to the DecoratorDefinition,
# but later that parameters are not used during resolution or compilation.
$normalizedEnvDefinitions[$key] = decorate($compilableClosure)
->parameter('type', $matches[1]);
$keyWithoutType = str_replace($matches[1] . ':', '', $key);
$normalizedEnvDefinitions[$keyWithoutType] = get($key);
}
}
parent::__construct($normalizedEnvDefinitions);
}
}
# Factory could be configured by adding different processors - predefined and custom ones
class EnvVarProcessorFactory {
private array $processors = [];
public function addProcessor(string $type, EnvVarProcessor $processor): void {
$this->processors[$type] = $processor;
}
public function getProcessor(string $type) {
return $this->processors[$type];
}
}
class MyService {
public function __construct(array $hosts);
}
class ServiceDefinitions extends DefinitionArray {
public function __construct() {
parent::__construct( [MyService::class=> autowire()->constructorParameter('hosts', get('env(HOSTS_LIST)'))]);
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Given
PHP-DI/src/Definition/DecoratorDefinition.php
Line 13 in b8126d0
PHP-DI/src/Definition/FactoryDefinition.php
Line 30 in b8126d0
DecoratorDefinition extends FactoryDefinition, but resolving script does not pass parameters to decorator callable as it is done in the FactoryResolver.
PHP-DI/src/Definition/Resolver/DecoratorResolver.php
Line 75 in b8126d0
PHP-DI/src/Definition/Resolver/FactoryResolver.php
Line 80 in b8126d0
Proposal
Parameters from $definition->getParameters() should be added to the decorator factory callable call.
call_user_func method call in DecoratorResolver.
call_user_func method call in Compiler.
I think plain parameters (without resolution) would be enough, because you already have your $value resolved, and you have $container, I do not think you need to pass unresolved definitions as a parameters, you can resolve everything from container using your factory callable.
How to use then
And when you create your definition, for example using the helper, you do:
When it is useful
When you want to decorate scalar values, for example value from EnvironmentVariableDefinition.
Environment variable could be resolved only to string value now, but with decorator you can decorate your definition, and then split your string, cast it, or even create a value object from it.
The text was updated successfully, but these errors were encountered: