75
29
Ok, so yesterday we had a big talk with other people from the Magento community regarding the direct use of the ObjectManager
in classes/templates.
I'm already aware of the reasons why we shouldn't use the ObjectManager directly, quoting Alan Kent :
There are several reasons. The code will work, but it is best practice to not reference the ObjectManager class directly.
- Because we say so! ;-) (better expressed as consistent code is good code)
- The code could be used with a different dependency injection framework in the future
- Testing is easier - you pass in mock arguments for the required class, without having to provide a mock ObjectManager
- It keeps dependencies clearer - it is obvious what the code depends on via constructor list, rather than having dependencies hidden in the middle of the code
- It encourages programmers to think about concepts like encapsulation and modularization better - if the constructor gets big, maybe it is a sign the code needs refactoring
From what I've seen in StackExchange, a lot of people tend to go for the easy/short/not recommended solution for example something like this:
<?php
//Get Object Manager Instance
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
//Load product by product id
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($id);
Instead of going through the painful but recommended process of:
- creating a module
- declaring preferences
- inject dependencies
- declare a public method
However, and here comes the dilemma, Magento 2 core files often call the ObjectManager directly. A quick example can be found here: https://github.com/magento/magento2/blob/develop/app/code/Magento/GoogleOptimizer/Block/Adminhtml/Form.php#L57
So here are my questions:
- Why is Magento doing what they recommend us not to do ? Does that mean there are some cases where we should use the
ObjectManager
directly? If so, what are those cases? - What are the consequences of using the ObjectManager directly?
at many places magento core team used directly Objectmanager concepts, then why we cant use it? – Rakesh Jesadiya – 2016-05-26T11:24:40.167
@Rakesh that's exactly my question ;) as we talked yesterday, I got concerned about that problem, I reckon this need clarification. – Raphael at Digital Pianism – 2016-05-26T11:25:42.827
3
Check this out: http://magento.stackexchange.com/q/28617/146
– Marius – 2016-05-26T11:29:52.6203
Relevant link: https://mwop.net/blog/2016-04-26-on-locators.html. The relevant bit of it would be
– nevvermind – 2016-05-26T12:29:10.627The intent of zend-servicemanager is for use as an Inversion of Control container. It was never intended as a general purpose service locator [...]
. Which it applies to M2, too. Also check theThere are valid use cases
section, which, again, applies here, too.Being scared of breaking things vs direct use of the ObjectManager is worse than I thought https://github.com/magento/magento2/commit/90f4decc16357dddfc91366d8b37f2668be18631
– Kristof at Fooman – 2016-05-27T14:59:01.9003There was some period of M2 development when OM was already there, but whole magento was not yet changed to use constructor injection. At that point many people replaced Mage::getSingleton() with ObjectManager::getInstance()->get(). Most of such usages were introduced at that period. Later all Mage::getSingleton() calls were replaced with constructor injection by a tool, but tool did not recognized ObjectManager::getInstance(), so it did not replace it with constructor injection. – Anton Kril – 2016-10-06T11:03:14.707
3
Possible duplicate of Magento 2 Helper instance
– Teja bhagavan Kollepara – 2017-02-20T12:08:00.0902@TejabhagavanKollepara did you read both questions ? There are similar but far from being duplicate from each other – Raphael at Digital Pianism – 2017-02-20T12:15:53.777
" if the constructor gets big, maybe it is a sign the code needs refactoring".. OK but what should be do when we have to extends a native MG2 class (it happens sometimes) which already have a huge constructo? – enrico69 – 2017-09-29T16:06:53.530