我已经定义了两个类(Environment和ConfigurationReader)。两者都被注册为共享依赖项。
Environment类尝试获取当前环境,但为此,需要通过ConfigurationReader读取配置文件。
序列图是:
课程是:
class Environment
{
...
public function resolve()
{
$config = DI::getDefault()->getCfg();
$config->getValue('pepe', 'db_name');
}
...
}
class ConfigurationReader
{
...
public function getValue($aConfig, $aKey)
{
$path = $this->getFile($aConfig);
}
protected function getFile($aConfig)
{
$env = DI::getDefault()->getEnv();
$path = 'config/' . $env->getShortName() . '/' . $aConfig . '.yml';
return $path;
}
...
}
并在index.php中注册并创建:
...
$di = new FactoryDefault();
$di->setShared('env', function() use ($di) {
$env = new Services\Environment($di);
$env->resolve();
return $env;
});
$di->setShared('cfg', function() use ($di) {
return new Services\ConfigurationReader($di);
});
$di->getShared('cfg');
$di->getShared('env');
...
因此,PHP在$config = DI::getDefault()->getCfg();
崩溃并说:
PHP致命错误:超出最大递归深度
有什么想法吗?
答案 0 :(得分:3)
一对评论
您正在将di传递给构造函数,但最终会以静态方式获取它(DI :: getDefault())
关于无限循环,因为cfg需要env谁需要cfg谁需要env等......
要让框架自动将DI注入您的服务,您应该实现InjectionAwareInterface(https://docs.phalconphp.com/en/latest/reference/di.html#automatic-injecting-of-the-di-itself)或 扩展Component类(如果您也需要事件管理,请使用Plugin而不是Component)。看一下这个讨论:https://forum.phalconphp.com/discussion/383/plugin-vs-component-what-s-the-difference-
关于您的用例,您没有提供足够的背景来获得详尽的答案,但我认为您可以将其简化为:
ConfigService:除非您使用来自不同env名称空间的配置,否则您应该将$ env-> getShortName()值的值传递给服务构造函数(而不是从env服务获取它)。在我们的应用程序中,env由nginx根据域名或其他参数确定,并作为环境变量传递给php。此外,如果您没有数百个配置文件,并且您的应用程序严重依赖它们,您应该在实例化时读取并解析它们并将配置存储在服务中(作为关联数组,配置对象或任何您喜欢)。添加一些缓存层以避免浪费资源解析每个请求上的所有文件。 Phalcons提供了Config组件。它带有文件适配器(只有ini和关联数组格式,但您可以轻松实现自己的yml适配器)。如果您的大多数应用程序配置依赖于可配置的值,那么这可能是您想要实例化的第一个组件(或者至少在di中声明)。它不应该依赖于其他服务。
EnvService:您可以通过调用配置服务来访问您的配置值(如果您要扩展Component,您可以执行类似$ this-> cfg-> getValue($ key))的操作。