0

I've written a console for invoicing frontend orders

https://github.com/DominicWatts/AutoInvoice/blob/master/Console/Command/Invoice.php

If I put Magento\Sales\Model\Service\InvoiceService in the constructor and run setup:di:compile magento console throws an 'Area Code Not Set' error.

You can't set area code as part of the constructor because when you run this and other console commands you see 'Area Code Already Set' error.

I understand state and why setting the 'area' is necessary.

My workaround is to do the following

use Magento\Sales\Model\Service\InvoiceService; 
protected function execute(InputInterface $input, OutputInterface $output)
{
 $this->state->setAreaCode(\Magento\Framework\App\Area::AREA_GLOBAL);
 $this->method();
}
public function method()
{
 $this->_objectManager = \Magento\Framework\App\ObjectManager::getInstance();
 $this->invoiceService = $this->_objectManager->create(InvoiceService::class);
 // do stuff
}

So basically using object manager at runtime instead of injecting. I'm constantly reading that using the object manager is bad. Therefore I feel like I'm not understanding a key concept.

So my questions are this:

a) Is this the right way to work around the issue?

b) If it's not - what is the correct approach?

c) Does using object manager add resource overhead? Or is it more that it will be deprecated at some stage.

asked May 31, 2019 at 22:46

2 Answers 2

3

It seems that when the class Magento\Sales\Model\Service\InvoiceService is injected, it calls some functions that cause the error. Since it doesn't happen when you use the ObjectManager directly, I suggest that you will try to inject Magento\Sales\Model\Service\InvoiceService\Proxy in the constructor. This will cause that the code will only call the functions that you use and won't call the functions that cause the error.

Read more about proxies here: https://devdocs.magento.com/guides/v2.3/extension-dev-guide/proxies.html

Regarding to your questions:

a+c) Using the object manager directly is bad for unit testing, because if you write unit tests, this code will make it impossible to inject mocks into the constructor. I don't know about any other reasons not to use the object manager directly.

b) The correct approach is to use the dependency injection - so proxy solution is the right approach (if it helps to resolve the error).

answered Jun 1, 2019 at 8:13
5
  • You have opened my eyes to proxies. I'm looking forward to trying this out. See it if works. I like the idea of lazy loading among other things to avoid dependency loop. One thing though. devdocs.magento.com/guides/v2.3/coding-standards/… says 2.5. Proxies and interceptors MUST NEVER be explicitly requested in constructors. Which has kinda blew my mind. I would have thought that's the only way to use them efficiently. Commented Jun 1, 2019 at 23:24
  • Yep works - or at least in the context I'm using it Commented Jun 4, 2019 at 12:00
  • Yes, you are right, but they suggest that you can inject the proxy using a di.xml file - github.com/magento/magento-coding-standard/issues/18 Commented Jun 10, 2019 at 14:53
  • So I guess something like this will work - <type name="MyController"> <arguments> <argument name="invoiceService" xsi:type="object">Magento\Sales\Model\Service\InvoiceService\Proxy</argument> </arguments> </type> Commented Jun 10, 2019 at 14:55
  • I think I follow what you are saying but I will happily award points if you put together an answer Commented Jun 11, 2019 at 11:25
0

Just to clarify accepted answer the solution was indeed

public function __construct(
 \Magento\Sales\Model\Service\InvoiceService\Proxy $invoiceService
) {
 $this->invoiceService = $invoiceService;
 parent::__construct();
}

Update

However this https://devdocs.magento.com/guides/v2.3/coding-standards/technical-guidelines.html states

  • 2.5. Proxies and interceptors MUST NEVER be explicitly requested in constructors.

And sure enough I was messing around with https://github.com/magento/magento-coding-standard Magento Coding Standard rules for PHP_CodeSniffer.

Sure enough:

FOUND 1 ERROR AND 3 WARNINGS AFFECTING 4 LINES
--------------------------------------------------------------------------------
 63 | ERROR | Proxies and interceptors MUST never be explicitly requested in
 | | constructors.

So maybe my initial approach was correct.

answered Jun 4, 2019 at 12:02
2
  • how did you resolve this error Proxies and interceptors MUST NEVER be explicitly requested in constructors ? Commented Jul 24, 2019 at 7:02
  • @MohitRane in my opinion my original workaround is the best solution Commented Jul 24, 2019 at 14:01

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.