Symfony DI: Uncaught ArgumentCountError: слишком мало аргументов для функции App::__construct(), 0 передано в index.php в строке 28 и ожидается ровно 1
Я пытаюсь реализовать контейнер внедрения зависимости Symfonys.
У меня установлено 2 контейнера, один для базы данных и один для пользователя системы.
а я пользуюсьaddArgument()
"к обоим App
класс и SystemUser
класс, подталкивая к App
класс SystemUser
объект, и для SystemUser
класс Database
объект.
index.php:
require_once 'vendor/autoload.php';
use TestingDI\App;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
$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');
# Initialize App class
$app = new App();
app.php:
<?php
namespace TestingDI;
use TestingDI\SystemUser;
class App {
public $systemUser;
public function __construct(SystemUser $systemUser)
{
var_dump($systemUser);
}
}
Я вижу мой результат var_dump с объектом, но продолжаю получать эту ошибку:
Неустранимая ошибка PHP: Uncaught ArgumentCountError: слишком мало аргументов для функции TestingDI\App::__construct(), 0 передано в /www/potato/symfony-di/index.php в строке 28 и ровно 1 ожидается в / www / potato / symfony -ди / testingdi / app.php:12
Трассировки стека:
0 /www/potato/symfony-di/index.php(28): TestingDI \ App -> __ construct ()
1 {main} добавлено в /www/potato/symfony-di/testingdi/App.php в строке 12
Это мои другие занятия:
SystemUser.php
<?php
namespace TestingDI;
use TestingDI\Database;
class SystemUser {
public $db;
public function __construct( Database $database )
{
$this->db = $database;
}
}
database.php
<?php
namespace TestingDI;
class Database {
public function __construct()
{
}
}
1 ответ
Кажется, что существует базовое неправильное представление о том, что такое внедрение зависимостей и как его использовать.
Поскольку вы используете контейнер зависимостей для создания различных частей вашего приложения, вы должны получать эти объекты из контейнера, а не создавать их экземпляры напрямую.
И, если вы собираетесь создавать их экземпляры напрямую (например, 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 делать всю работу за вас. Что, конечно, учитывая, насколько многословно ваше контейнерное определение, кажется довольно бессмысленным.
Но вы можете позволить силе автопроводки выполнять большую часть тяжелой работы за вас и делать следующее:
$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.