Auto wiring a shared dependency
jtojnar opened this issue · comments
I tried using ReflectionDelegate
to achieve auto-wiring and it works mostly great. The issue occurs when I register some services as shared – then they won’t be autowired any more.
See the following simplified example:
<?php
require __DIR__ . '/vendor/autoload.php';
class Logger {
public function __construct(string $name) { }
}
class Authentication {
public function __construct(Logger $logger) { }
}
class AboutController {
public function __construct(Authentication $authentication) { }
}
$container = new League\Container\Container();
// Register the reflection container as a delegate to enable auto wiring.
$container->delegate(new League\Container\ReflectionContainer(true));
$container
->add(Authentication::class)
->setShared()
;
$container
->add(Logger::class)
->addArgument('selfoss')
->setShared()
;
var_dump($container->get(AboutController::class));
Fatal error: Uncaught ArgumentCountError: Too few arguments to function Authentication::__construct(), 0 passed and exactly 1 expected in test.php:10
Stack trace:
#0 [internal function]: Authentication->__construct()
#1 src/Definition/Definition.php(212): ReflectionClass->newInstanceArgs(Array)
#2 src/Definition/Definition.php(175): League\Container\Definition\Definition->resolveClass('Authentication')
#3 src/Definition/Definition.php(154): League\Container\Definition\Definition->resolveNew()
#4 src/Definition/DefinitionAggregate.php(79): League\Container\Definition\Definition->resolve()
#5 src/Container.php(175): League\Container\Definition\DefinitionAggregate->resolve('Authentication')
#6 src/Container.php(118): League\Container\Container->resolve('Authentication')
#7 src/Argument/ArgumentResolverTrait.php(45): League\Container\Container->get('Authentication')
#8 src/Argument/ArgumentResolverTrait.php(107): League\Container\ReflectionContainer->resolveArguments(Array)
#9 src/ReflectionContainer.php(58): League\Container\ReflectionContainer->reflectArguments(Object(ReflectionMethod), Array)
#10 src/Container.php(203): League\Container\ReflectionContainer->get('AboutController')
#11 src/Container.php(118): League\Container\Container->resolve('AboutController')
#12 test.php(33): League\Container\Container->get('AboutController')
#13 {main}
thrown in test.php on line 10
I could addArguments
the dependencies explicitly but doing it for all of the shared services would be annoying.
You actually don't need to setShared
, by doing that, you're telling the container that Authentication::class
has a definition in the container, so no autowiring is attempted. However, you have the reflection container set to cache resolutions, so anything resolved through it will, in effect, be shared anyway.