7

I cannot use ScopeConfigInterface $scopeConfig when extending certain objects

di.xml

<preference for="Magento\Framework\Logger\Monolog" type="Foo\Log\Logger\FooLog" />

<virtualType name="helper" type="Foo\Log\Helper\Data" />

       <type name="Foo\Log\Logger\FooLog">
          <arguments>
             <argument name="helper" xsi:type="object">Foo\Log\Helper\Data</argument>
          </arguments>
       </type>

FooLog.php

    public function __construct(
     \Foo\Log\Helper\Data $dataHelper
   )
    {
        $this->_scopeConfig = $scopeConfig;
    }

Data.php

public function __construct(ScopeConfigInterface $scopeConfig)
{
    $this->_scopeConfig = $scopeConfig;
}

$this->_scopeConfig->getValue('dev/debug/foo_bar_config', 'default');

Error:

Circular dependency: Magento\Store\Model\ResourceModel\Config\Collection\Scoped depends on Magento\Store\Model\ResourceModel\Config\Collection\Scoped and vice versa.

I can't even get existing configs like in CreateOrder.php

 $this->scopeConfig->getValue(self::CONFIG_PATH_MERCHANT_ID, $this->sessionQuote->getStoreId());

The issue is, that using ScopeConfigInterface $scopeConfig is only not possible to use for certain objects, if I try to extend some other objects like

 <preference for="Magento\Cms\Controller\Index\Index" type="Foo\Log\Helper\Data" />

it works

*UPDATE

Tried with proxy class - success

<type name="Foo\Log\Helper\Data">
    <arguments>
        <argument name="configinterface" xsi:type="object">Magento\Framework\App\Config\ScopeConfigInterface\Proxy</argument>
    </arguments>
</type>

Data.php

        public function __construct(
    \Magento\Framework\App\Config\ScopeConfigInterface\Proxy $scopeConfig)
            {
                $this->_scopeConfig = $scopeConfig;
               $host =  $this->_scopeConfig->getValue('dev/debug/remote_server_host');
               // error after getValue
            }
}
14

Your error message is:

Circular dependency: Magento\Store\Model\ResourceModel\Config\Collection\Scoped depends on Magento\Store\Model\ResourceModel\Config\Collection\Scoped and vice versa.

To understand what happens you should look at class from error message: Magento\Store\Model\ResourceModel\Config\Collection\Scoped

In its constructor we see a dependency on \Psr\Log\LoggerInterface

As we can see in your di.xml you create a preference for Magento\Framework\Logger\Monolog: <preference for="Magento\Framework\Logger\Monolog" type="Foo\Log\Logger\FooLog"/>

Magento\Framework\Logger\Monolog is a preference for \Psr\Log\LoggerInterface itself. So you effectively create a preference for \Psr\Log\LoggerInterface, and your Foo\Log\Logger\FooLog will be provided to constructor of \Magento\Store\Model\ResourceModel\Config\Collection\Scoped whenever it's created.

Now if we look deeper at implementation of ScopeConfigInterface requested by your helper, we will see that it depends on \Magento\Store\Model\ResourceModel\Config\Collection\Scoped.

So we got into situation when to create \Foo\Log\Logger\FooLog we need instance ScopedConfigInterface, and to create ScopedConfigInterface we need \Magento\Store\Model\ResourceModel\Config\Collection\Scoped that requires \Foo\Log\Logger\FooLog: circular dependency.

To resolve this you should either not use ScopeConfigInterface in your helper or substitute it with Proxy (lazy object loading) to break circular dependency.

We will think about better circular dependency detection algorithm that will display more informative messages.

  • wow, this is a super clear explanation thanks a lot for this. To solve this: a) is there another way to get values from admin backend without using ScopeConfigInterface? b) I think I do not fully get the grasp of the Proxy thing Do I need to use ScopeConfigInterface\Proxy in my helper or what is the meaning of this? So when I like to use a config from the backend, what would be the prefered way to handle this? – xhallix Dec 24 '15 at 16:18
  • Added link to proxy/lazy-loading documentation in the answer – Anton Kril Dec 24 '15 at 16:31
  • thanks. one last thing, would you suggest to use a proxy or to avoid using scopeconfiginterface and use some other method instead? – xhallix Dec 24 '15 at 17:04
  • Use a proxy for ScopeConfigInterface to avoid ScopeConfigInterface instantiation during logger instantiation – Anton Kril Dec 24 '15 at 17:33
  • I used the proxy for ScopeConfigInterface but this seems not to fix this, please see my latest update – xhallix Dec 24 '15 at 19:52
2

in di.xml you may use preferences or virtual type tag which make circular dependence check on di.xml

  • thanks for the answer, but I already used a preference. It is just not working within my own module somehow – xhallix Dec 24 '15 at 8:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.