PHP-DI无法使用构造函数参数注入创建的类

时间:2017-09-04 10:29:17

标签: php dependency-injection php-di

我尝试用PHP-DI创建一个项目,但我遇到了问题。

这是追踪:

trace

以下是代码:

容器类:

$this->containerBuilder->addDefinitions([
        'Configuration' => DI\Object('Hetwan\Core\Configuration')->constructor($this->getRootDir().'/app/config/config.yml'),
        'Database' => DI\object('Hetwan\Core\Database')
]);

配置类:

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;
}
}

数据库类:

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')并且有效。

但是在创建Database类时我认为PHP-DI尝试重新创建一个Configuration实例,我不知道为什么因为单例实例已经在这里了。

感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

注释<!DOCTYPE html> <html> <head> <title></title> </head> <body onload="loadHandler()"> <p>Drag me!</p> <script type="text/javascript"> function loadHandler() { document.getElementsByTagName('p').setAttribute('draggable', true); } </script> </body> </html>很可能被解释为类名,基于文件的命名空间和使用声明,而不是容器中服务的名称。

没有任何其他线索,自动DI可能会寻找与完全合格的类名相匹配的服务,即@var Configuration。但是,您的服务已注册为Hetwan\Core\Configuration,因此无法匹配。因此,DI回退到尝试使用Configuration自动构造实例但是失败,因为构造函数具有必需参数。

我怀疑您需要做的是使用完全限定名称注册您的服务,如下所示:

new \Hetwan\Core\Configuration();

然后,当它去查找$this->containerBuilder->addDefinitions([ 'Hetwan\Core\Configuration' => DI\Object('Hetwan\Core\Configuration') ->constructor($this->getRootDir().'/app/config/config.yml') ]); 的实例时,它将找到该服务,而不是尝试运行构造函数。

PHP-DI手册shows how you can simplify this使用the magic constant ::class来:

\Hetwan\Core\Configuration

或者,您可以告诉PHP-DI注入哪些服务,而不是根据属性类型according to the documentation on annotations进行猜测:

use Hetwan\Core\Configuration;

$this->containerBuilder->addDefinitions([
        Configuration::class => DI\Object()
            ->constructor($this->getRootDir().'/app/config/config.yml')
]);