-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
Closed as not planned
Closed as not planned
Copy link
Description
Symfony version(s) affected
6.3.0
Description
The new #[AutowireServiceClosure]
attribute introduced in #49628 by @nicolas-grekas does not seem to work together with #[Target]
.
In CheckExceptionOnInvalidReferenceBehaviorPass.php line 86:
The service "MyExtension" has a dependency on a non-existent service "MyCache".
How to reproduce
class MyExtension
{
public function __construct(
#[AutowireServiceClosure(MyService::class)]
private Closure $myService,
#[Target('myTargetName')]
#[AutowireServiceClosure(MyCache::class)]
private Closure $cache,
) {}
}
Possible Solution
I tried debugging it but couldn't get it to work. I feel we should add a new condition here:
symfony/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
Lines 316 to 349 in 5b66f26
if ($attribute instanceof AutowireCallable) { | |
$value = (new Definition($type = \is_string($attribute->lazy) ? $attribute->lazy : ($type ?: 'Closure'))) | |
->setFactory(['Closure', 'fromCallable']) | |
->setArguments([\is_array($value) ? $value + [1 => '__invoke'] : $value]) | |
->setLazy($attribute->lazy || 'Closure' !== $type && 'callable' !== (string) $parameter->getType()); | |
} elseif ($lazy = $attribute->lazy) { | |
$definition = (new Definition($type)) | |
->setFactory('current') | |
->setArguments([[$value ??= $getValue()]]) | |
->setLazy(true); | |
if (!\is_array($lazy)) { | |
if (str_contains($type, '|')) { | |
throw new AutowiringFailedException($this->currentId, sprintf('Cannot use #[Autowire] with option "lazy: true" on union types for service "%s"; set the option to the interface(s) that should be proxied instead.', $this->currentId)); | |
} | |
$lazy = str_contains($type, '&') ? explode('&', $type) : []; | |
} | |
if ($lazy) { | |
if (!class_exists($type) && !interface_exists($type, false)) { | |
$definition->setClass('object'); | |
} | |
foreach ($lazy as $v) { | |
$definition->addTag('proxy', ['interface' => $v]); | |
} | |
} | |
if ($definition->getClass() !== (string) $value || $definition->getTag('proxy')) { | |
$value .= '.'.$this->container->hash([$definition->getClass(), $definition->getTag('proxy')]); | |
} | |
$this->container->setDefinition($value = '.lazy.'.$value, $definition); | |
$value = new Reference($value); | |
} | |
$arguments[$index] = $value; |
I tried adding:
} elseif ($attribute instanceof AutowireServiceClosure && $target !== []) {
$arguments[$index] = $getValue();
}
but that resulted in
In DefinitionErrorExceptionPass.php line 51:
[Symfony\Component\DependencyInjection\Exception\RuntimeException]
Cannot autowire service "MyExtension": "#[Target('myTargetName')" on argument "$cache" of method "__construct()"
Additional Context
No response