PHP-DI 无法使用构造函数参数注入创建的 class
PHP-DI Can't inject created class with constructor parameters
我尝试用 PHP-DI 做一个项目,但我遇到了问题。
这是痕迹:
代码如下:
容器class:
$this->containerBuilder->addDefinitions([
'Configuration' => DI\Object('Hetwan\Core\Configuration')->constructor($this->getRootDir().'/app/config/config.yml'),
'Database' => DI\object('Hetwan\Core\Database')
]);
配置class:
namespace Hetwan\Core;
use Symfony\Component\Yaml\Yaml;
class Configuration
{
private $attrs;
public function __construct($configFilePath)
{
$this->attrs = Yaml::parse(file_get_contents($configFilePath));
}
public function get($attrPath)
{
$el = $this->attrs;
foreach (explode('.', $attrPath) as $attr)
{
if (!isset($el[$attr]))
throw new ConfigurationException("Unable to get '{$attrPath}'.\n");
$el = $el[$attr];
}
return $el;
}
}
数据库class:
namespace Hetwan\Core;
use Hetwan\Core\Configuration;
class Database
{
/**
* @Inject
* @var Configuration
*/
private $config;
private $entityManager;
public function create($entitiesPath)
{
$dbParameters = [
'driver' => 'pdo_mysql',
'user' => $config->get('database.user'),
'password' => $config->get('database.password'),
'dbname' => $config->get('database.name')
];
$this->entityManager = EntityManager::create($dbParameters, Setup::createAnnotationMetadataConfiguration([$entitiesPath], false));
}
public function getEntityManager()
{
return $this->entityManager;
}
}
我可以毫无问题地访问 $container->get('Configuration')
并且它有效。
但是在创建数据库时 class 我想 PHP-DI 尝试重新创建一个配置实例,我不知道为什么,因为这里已经有一个单例实例。
感谢您的帮助!
注释 @var Configuration
可能被解释为 class 名称,基于文件的命名空间和使用声明,而不是容器中服务的名称。
如果没有任何其他线索,自动 DI 可能会寻找与完全限定的 class 名称匹配的服务,即 Hetwan\Core\Configuration
。但是,您的服务注册为 Configuration
,因此不匹配。因此 DI 回退到尝试使用 new \Hetwan\Core\Configuration();
自动构造一个实例但失败了,因为构造函数有一个必需的参数。
我怀疑您需要做的是使用完全限定名称注册您的服务,如下所示:
$this->containerBuilder->addDefinitions([
'Hetwan\Core\Configuration' => DI\Object('Hetwan\Core\Configuration')
->constructor($this->getRootDir().'/app/config/config.yml')
]);
然后当它去寻找 \Hetwan\Core\Configuration
的实例时,它会找到该服务,而不是尝试 运行 构造函数。
PHP-DI手册shows how you can simplify this using the magic constant ::class
至:
use Hetwan\Core\Configuration;
$this->containerBuilder->addDefinitions([
Configuration::class => DI\Object()
->constructor($this->getRootDir().'/app/config/config.yml')
]);
或者,您可以告诉 PHP-DI 要注入哪个服务,而不是让它根据 属性、according to the documentation on annotations:
的类型进行猜测
/**
* @Inject("Configuration")
*/
private $config;
我尝试用 PHP-DI 做一个项目,但我遇到了问题。
这是痕迹:
代码如下:
容器class:
$this->containerBuilder->addDefinitions([
'Configuration' => DI\Object('Hetwan\Core\Configuration')->constructor($this->getRootDir().'/app/config/config.yml'),
'Database' => DI\object('Hetwan\Core\Database')
]);
配置class:
namespace Hetwan\Core;
use Symfony\Component\Yaml\Yaml;
class Configuration
{
private $attrs;
public function __construct($configFilePath)
{
$this->attrs = Yaml::parse(file_get_contents($configFilePath));
}
public function get($attrPath)
{
$el = $this->attrs;
foreach (explode('.', $attrPath) as $attr)
{
if (!isset($el[$attr]))
throw new ConfigurationException("Unable to get '{$attrPath}'.\n");
$el = $el[$attr];
}
return $el;
}
}
数据库class:
namespace Hetwan\Core;
use Hetwan\Core\Configuration;
class Database
{
/**
* @Inject
* @var Configuration
*/
private $config;
private $entityManager;
public function create($entitiesPath)
{
$dbParameters = [
'driver' => 'pdo_mysql',
'user' => $config->get('database.user'),
'password' => $config->get('database.password'),
'dbname' => $config->get('database.name')
];
$this->entityManager = EntityManager::create($dbParameters, Setup::createAnnotationMetadataConfiguration([$entitiesPath], false));
}
public function getEntityManager()
{
return $this->entityManager;
}
}
我可以毫无问题地访问 $container->get('Configuration')
并且它有效。
但是在创建数据库时 class 我想 PHP-DI 尝试重新创建一个配置实例,我不知道为什么,因为这里已经有一个单例实例。
感谢您的帮助!
注释 @var Configuration
可能被解释为 class 名称,基于文件的命名空间和使用声明,而不是容器中服务的名称。
如果没有任何其他线索,自动 DI 可能会寻找与完全限定的 class 名称匹配的服务,即 Hetwan\Core\Configuration
。但是,您的服务注册为 Configuration
,因此不匹配。因此 DI 回退到尝试使用 new \Hetwan\Core\Configuration();
自动构造一个实例但失败了,因为构造函数有一个必需的参数。
我怀疑您需要做的是使用完全限定名称注册您的服务,如下所示:
$this->containerBuilder->addDefinitions([
'Hetwan\Core\Configuration' => DI\Object('Hetwan\Core\Configuration')
->constructor($this->getRootDir().'/app/config/config.yml')
]);
然后当它去寻找 \Hetwan\Core\Configuration
的实例时,它会找到该服务,而不是尝试 运行 构造函数。
PHP-DI手册shows how you can simplify this using the magic constant ::class
至:
use Hetwan\Core\Configuration;
$this->containerBuilder->addDefinitions([
Configuration::class => DI\Object()
->constructor($this->getRootDir().'/app/config/config.yml')
]);
或者,您可以告诉 PHP-DI 要注入哪个服务,而不是让它根据 属性、according to the documentation on annotations:
的类型进行猜测/**
* @Inject("Configuration")
*/
private $config;