Я пытаюсь реализовать контейнер внедрения зависимости 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 {главная}
добавлено в /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()
{
}
}
Кажется, что существует неправильное представление о том, что такое внедрение зависимостей и как его использовать.
Поскольку вы используете контейнер зависимостей для создания различных частей вашего приложения, вы должны получать эти объекты из контейнера, не создавать их непосредственно.
И, если вы собираетесь создавать их экземпляры напрямую (например, 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
Других решений пока нет …