获得共享服务的最大递归

时间:2016-04-06 22:21:53

标签: dependency-injection phalcon

我已经定义了两个类(Environment和ConfigurationReader)。两者都被注册为共享依赖项。

Environment类尝试获取当前环境,但为此,需要通过ConfigurationReader读取配置文件。

序列图是:

enter image description here

课程是:

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致命错误:超出最大递归深度

有什么想法吗?

1 个答案:

答案 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))的操作。