Q:

Maximum recursion getting shared service

I have defined two classes (Environment and ConfigurationReader).  Both are registered as shared dependencies. 
The Environment class tries get the current environment, but for this, needs read a configuration file via ConfigurationReader. 
The sequence diagram is:

The classes are:
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;
   }
   ...
}

And are registered and created in the 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');
...

So, PHP crash at $config = DI::getDefault()->getCfg(); and says:

PHP Fatal error:  Maximum recursion depth exceeded

Any ideas ? 

A:

A couple remarks

You're passing the di to the constructor, but end up getting it statically (DI::getDefault())
regarding the infinite loop, it's because cfg needs env who needs cfg who needs env etc.....

To have the framework automatically injecting the DI into your service you should either implement InjectionAwareInterface (https://docs.phalconphp.com/en/latest/reference/di.html#automatic-injecting-of-the-di-itself) or 
extend the Component class (If you need event management too, use Plugin instead of Component ).  Have a look at this discussion : https://forum.phalconphp.com/discussion/383/plugin-vs-component-what-s-the-difference-
Regarding your use case, you don't give enough context for an exhaustive answer, but I think you could simplify it as:

ConfigService: Unless you use configs from different env namespaces, you should pass the value of $env->getShortName() value to the service constructor (without getting it from the env service).  In our apps the env is determined by nginx based on the domain name or other parameters and passed as an environment variable to php.  Also, if you don't have hundreds of config files, and your app heavily relies on them, you should read and parse them once on instantiation and store the configs in the service (as associative array, config objects, or whatever you prefer).  Add some cache layer to avoid wasting resource parsing all your files on each request.  Phalcons provide The Config component to do so.  It comes with file adapters (only ini and associative array format but you could easily implement your own yml adapter).  If most of your app config relies on configurable values, that will probably be the first component you want to instantiate (or at least declare in the di).  It shouldn't dependencies to other services. 
EnvService: You can access your config values by calling the config service (If you have it to extend Component, you can do something like $this->cfg->getValue($key)). 