Dependency injection

Until now, we have seen how the object manager has control over the instantiation of dependencies. However, by convention, the object manager isn't supposed to be used directly in Magento. Rather, it should be used for system-level things that bootstrap Magento. We are encouraged to use the module's etc/di.xml file to instantiate objects.

Let's dissect one of the existing di.xml entries, such as the one found under the vendor/magento/module-admin-notification/etc/adminhtml/di.xml file for the MagentoFrameworkNotificationMessageList type:

<type name="MagentoFrameworkNotificationMessageList">
    <arguments>
        <argument name="messages" xsi:type="array">
            <item name="baseurl" xsi:type="string"> MagentoAdminNotificationModelSystem MessageBaseurl</item>
            <item name="security" xsi:type="string"> MagentoAdminNotificationModelSystem MessageSecurity</item>
            <item name="cacheOutdated" xsi:type="string"> MagentoAdminNotificationModelSystem MessageCacheOutdated</item>
            <item name="media_synchronization_error" xsi:type="string">MagentoAdminNotificationModel SystemMessageMediaSynchronizationError</item>
            <item name="media_synchronization_success" xsi:type="string">MagentoAdminNotificationModel SystemMessageMediaSynchronizationSuccess</item>
        </argument>
    </arguments>
</type>

Basically, what this means is that whenever an instance of MagentoFrameworkNotificationMessageList is being created, the messages parameter is passed on to the constructor. The messages parameter is being defined as an array, which further consists of other string type items. In this case, values of these string type attributes are class names, as follows:

  • MagentoFrameworkObjectManagerObjectManager
  • MagentoAdminNotificationModelSystemMessageBaseurl
  • MagentoAdminNotificationModelSystemMessageSecurity
  • MagentoAdminNotificationModelSystemMessageCacheOutdated
  • MagentoAdminNotificationModelSystemMessageMediaSynchronizationError
  • MagentoAdminNotificationModelSystemMessageMediaSynchronizationSuccess

If you now take a look at the constructor of MessageList, you will see that it is defined in the following way:

public function __construct(
    MagentoFrameworkObjectManagerInterface $objectManager,
    $messages = []
)
{
    //Method body here...
}

If we modify the MessageList constructor as follows, the code will work:

public function __construct(
    MagentoFrameworkObjectManagerInterface $objectManager,
    $someVarX = 'someDefaultValueX',
    $messages = []
)
{
    //Method body here...
}

After modification:

public function __construct(
    MagentoFrameworkObjectManagerInterface $objectManager,
    $someVarX = 'someDefaultValueX',
    $messages = [],
    $someVarY = 'someDefaultValueY'
)
{
    //Method body here...
}

However, if we change the MessageList constructor to one of the following variations, the code will fail to work:

public function __construct(
    MagentoFrameworkObjectManagerInterface $objectManager,
    $Messages = []
)
{
    //Method body here...
}

Another variation is as follows:

public function __construct(
    MagentoFrameworkObjectManagerInterface $objectManager,
    $_messages = []
)
{
    //Method body here...
}

The name of the $messages parameter in the constructor of the PHP class has to exactly match the name of the argument within the arguments' list of di.xml. The order of parameters in the constructor does not really matter as much as their naming.

Looking further in the MessageList constructor, if we execute func_get_args somewhere within it, the list of items within the $messages parameter will match and exceed the one shown in vendor/magento/module-admin-notification/etc/adminhtml/di.xml. This is so because the list is not final, as Magento collects the DI definitions from across entire the platform and merges them. So, if another module is modifying the MessageList type, the modifications will be reflected.

If we perform a string search within all the di.xml files across the entire Magento code base for <type name="MagentoFrameworkNotificationMessageList">, this will yield some additional di.xml files that have their own additions to the MessageList type, as follows:

//vendor/magento/module-indexer/etc/adminhtml/di.xml
<type name="MagentoFrameworkNotificationMessageList">
    <arguments>
        <argument name="messages" xsi:type="array">
            <item name="indexer_invalid_message" xsi:type="string">MagentoIndexerModelMessage Invalid</item>
        </argument>
    </arguments>
</type>

//vendor/magento/module-tax/etc/adminhtml/di.xml
<type name="MagentoFrameworkNotificationMessageList">
    <arguments>
        <argument name="messages" xsi:type="array">
            <item name="tax" xsi:type="string">Magento TaxModelSystemMessageNotifications</item>
        </argument>
    </arguments>
</type>

What this means is that the MagentoIndexerModelMessageInvalid and MagentoTaxModelSystemMessageNotifications string items are being added to the messages argument and are being made available within the MessageList constructor.

In the preceding DI example, we only had the $messages parameter defined as one argument of the array type, and the rest were its array items.

Let's take a look at a DI example for another type definition. This time, it is the one found under the vendor/magento/module-backend/etc/di.xml file and which is defined as follows:

<type name="MagentoBackendModelUrl">
    <arguments>
        <argument name="scopeResolver" xsi:type="object"> MagentoBackendModelUrlScopeResolver</argument>
        <argument name="authSession" xsi:type="object"> MagentoBackendModelAuthSessionProxy</argument>
        <argument name="formKey" xsi:type="object"> MagentoFrameworkDataFormFormKeyProxy</argument>
        <argument name="scopeType" xsi:type="const"> MagentoStoreModelScopeInterface::SCOPE_STORE </argument>
        <argument name="backendHelper" xsi:type="object"> MagentoBackendHelperDataProxy</argument>
    </arguments>
</type>

Here, you will see a type with several different arguments passed to the constructor of the MagentoBackendModelUrl class. If you now take a look at the constructor of the Url class, you will see that it is defined in the following way:

public function __construct(
    MagentoFrameworkAppRouteConfigInterface $routeConfig,
    MagentoFrameworkAppRequestInterface $request,
    MagentoFrameworkUrlSecurityInfoInterface $urlSecurityInfo,
    MagentoFrameworkUrlScopeResolverInterface $scopeResolver,
    MagentoFrameworkSessionGeneric $session,
    MagentoFrameworkSessionSidResolverInterface $sidResolver,
    MagentoFrameworkUrlRouteParamsResolverFactory $routeParamsResolverFactory,
    MagentoFrameworkUrlQueryParamsResolverInterface $queryParamsResolver,
    MagentoFrameworkAppConfigScopeConfigInterface $scopeConfig,
    $scopeType,
    MagentoBackendHelperData $backendHelper,
    MagentoBackendModelMenuConfig $menuConfig,
    MagentoFrameworkAppCacheInterface $cache,
    MagentoBackendModelAuthSession $authSession,
    MagentoFrameworkEncryptionEncryptorInterface $encryptor,
    MagentoStoreModelStoreFactory $storeFactory,
    MagentoFrameworkDataFormFormKey $formKey,
    array $data = []
) {
    //Method body here...
}

The __construct method here clearly has more parameters than what's defined in the di.xml file. What this means is that the type argument entries in di.xml do not necessarily cover all the class __construct parameters. The arguments that are defined in di.xml simply impose the types of individual parameters defined in the PHP class itself. This works as long as the di.xml parameters are of the same type or descendants of the same type.

Ideally, we would not pass the class type but interface into the PHP constructor and then set the type in di.xml. This is where the type, preference, and virtualType play a major role in di.xml. We have seen the role of type. Now, let's go ahead and see what preference does.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.172.115