0

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

这是跟踪:

痕迹

这是代码:

容器类:

$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 的实例,但我不知道为什么,因为这里已经有一个单例实例。

感谢您的帮助!

4

1 回答 1

2

根据文件的命名空间和使用声明,注释@var Configuration很可能被解释为类名,而不是容器中服务的名称。

在没有任何其他线索的情况下,自动 DI 可能会寻找与该完全限定类名匹配的服务,即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 手册展示了如何使用魔术常量::class来简化它:

use Hetwan\Core\Configuration;

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

或者,根据 annotations 的文档,您可以告诉 PHP-DI 要注入哪个服务,而不是让它根据属性的类型进行猜测:

/**
 * @Inject("Configuration")
 */
private $config;
于 2017-09-04T11:36:37.160 回答