Кажется, что существует базовое неправильное представление о том, что такое внедрение зависимостей и как его использовать.
Поскольку вы используете контейнер зависимостей для создания различных частей вашего приложения, вы должны получать эти объекты из контейнера , а не создавать их экземпляры напрямую.
И, если вы собираетесь создавать их экземпляры напрямую (например, new App()
), вы должны соблюдать правила обычного языка. В этом случае подпись конструктора:
public function __construct(SystemUser $systemUser)
Если вы вызываете конструктор, не передавая ему объект класса SystemUser
, он потерпит неудачу, точно так же, как и любой другой метод / функция, произойдет сбой, если вы вызовете его способом, не соответствующим его сигнатуре .
К тому времени, как ты это сделал
$app = $containerBuilder->get('app');
Ваше приложение уже "инициализировано", и вам вообще не нужно было звонить new
.
Делая это:
$containerBuilder = new ContainerBuilder();
$containerBuilder->register('database', '\TestingDI\Database');
$containerBuilder->register('system.user', '\TestingDI\SystemUser')
->addArgument(new Reference('database'));
$containerBuilder->register('app', '\TestingDI\App')
->addArgument(new Reference('system.user'));
$database = $containerBuilder->get('database');
$systemUser = $containerBuilder->get('system.user');
$app = $containerBuilder->get('app');
Вы делали эквивалент:
$database = new Database();
$systemUser = new SystemUser($database);
$app = new App($systemUser);
Только вы позволяли контейнеру DI делать всю работу за вас. Что, конечно, учитывая, насколько многословно ваше определение контейнера, кажется довольно бессмысленным.
Но вы можете позволить мощности autowiring сделать большую часть тяжелой работы за вас и сделать следующее:
$container = new ContainerBuilder();
$container->autowire( Database::class );
$container->autowire( SystemUser::class );
$container->autowire( App::class )
->setPublic( true );
$container->compile();
// this will get you an application instance with all the dependencies
// resolved and injected in the class.
$app = $container->get( App::class );
Теперь я замечаю, что у вас уже была подобная проблема, когда пробовал другую библиотеку DI , и теперь я понимаю, что вся проблема заключается в простом непонимании того, с какой проблемой работает контейнер DI