The article is believed to be useful for PHP developers who are mastering Magento 2 components. You will learn dependency inversion principle, functions of object manager and dependencies compiling. In case you have some questions, feel free to ask our certified developers for help.
Dependency injection is a design pattern based on the “inversion of control” principle. It involves objects relations to their dependencies. Instead of creating dependencies manually, all necessary dependencies are rendered to the object via the container. The approach helps to avoid excessive code coherence, as now the object is not required to its own dependencies but IoC container defines which functions are to be rendered to the object depending on configuration.
Dependency inversion principle states that high-level classes must use the abstractions of low-level objects but not deal with them directly. It also reduces code coherence and mitigates non-compatibility risk in case if object implementation is changed.
Object Manager
Magento 2 uses dependency injection for functionality that was represented by Mage in Magento 1.
1 2 3 4 5 6 7 8 9 10 11 12 |
namespace Magento\Backend\Model\Menu; class Builder { public function __construct( Magento\Backend\Model\Menu\ItemFactory $menuItemFactory, Magento\Backend\Model\Menu $menu ) { $this->_itemFactory = $menuItemFactory; $this->_menu = $menu; } } |
ObjectManager is used as a IoC container. It is responsible for:
- creating objects in factories and proxies.
- implementing singleton pattern returning the same object instance on subsequent requests.
- selecting a necessary implementation on interface request.
- creating classes automatically focusing on the arguments of the constructor.
ObjectManager is configured using di.xml files. These files contain the preferred interface implementation and also it shows ObjectManager to use the object as singleton or create a new instance every time it’s necessary. Each module can have global as well as area-specific di.xml files. Area-specific di.xml files should be used to configure dependencies for presentation layer when global di.xml files are for the rest.
Abstraction-implementation mappings and class rewrites
It is used when the constructor asks the object for its interface. ObjectManager uses the configuration when deciding which implementation should be executed for the current scope.
1 2 3 |
<config> <preference for="Magento\Core\Model\UrlInterface" type="Magento\Core\Model\Url" /> </config> |
The same approach can be used not only for replacing interface but for classes.
1 2 3 |
<config> <preference for="Magento\Core\Model\Url" type="Vendor\Module\Model\NewUrl" /> </config> |
Virtual Types
It allows changing the arguments of any dependency and hereby modifying the class behavior without affecting other classes that are dependent on the original.
1 2 3 4 5 6 7 |
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <virtualType name="moduleConfig" type="Magento\Core\Model\Config"> <arguments> <argument name="type" xsi:type="string">system</argument> </arguments> </virtualType> </config> |
ObjectManager should never be called directly, as Magento Framework does it automatically. The exception can be factory or proxy classes which are in most cases generated by framework automatically or unit tests and static magic methods (wakeup, sleep).
Magento 2 code contains direct ObjectManager calls but they shouldn’t be used as an example and exist only for backward compatibility.
Compiling dependencies
1 |
php bin/magento setup:di:compile |
Magento 2 uses a special utility to compile the dependencies of all classes. It compiles the file that contains the dependencies of all objects for ObjectManager based on constructor arguments with the help of php reflection features. Service classes such as factories, plugins, and proxies are also generated.