我正在尝试实现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致命错误:未捕获ArgumentCountError:函数TestingDI \ App :: __ construct()的参数太少,第28行的/www/potato/symfony-di/index.php中传递了0,而在/ www /中恰好期望了1马铃薯/symfony-di/testingdi/App.php:12
堆栈跟踪:
0 /www/potato/symfony-di/index.php(28):TestingDI \ App-> __ construct()
1 {main} 在第12行的/www/potato/symfony-di/testingdi/App.php中抛出
这些是我的其他课程:
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()
{
}
}
答案 0 :(得分:3)
关于什么是依赖注入以及如何使用它似乎有一个基本的误解。
由于您使用的是依赖容器来构建应用程序的不同部分,因此应该从容器中获取这些对象,而不是直接实例化它们。
而且,如果要直接实例化它们(例如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 );
我现在注意到您在trying a different DI library时已经遇到了类似的问题,并且我现在意识到整个问题都围绕着一个简单的误解,即对DI容器要处理的问题的误解