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?
The 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.