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.
3.144.172.115