What is the use of “mapping” node in di.xml in Magento 2?
-
07-02-2021 - |
Question
I am using Magento 2.2.5
have a look on file
vendor\magento\module-sales\etc\di.xml
<type name="Magento\Payment\Model\Checks\SpecificationFactory">
<arguments>
<argument name="mapping" xsi:type="array">
<item name="country" xsi:type="object">Magento\Payment\Model\Checks\CanUseForCountry</item>
<item name="currency" xsi:type="object">Magento\Payment\Model\Checks\CanUseForCurrency</item>
<item name="checkout" xsi:type="object">Magento\Payment\Model\Checks\CanUseCheckout</item>
<item name="internal" xsi:type="object">Magento\Payment\Model\Checks\CanUseInternal</item>
<item name="total" xsi:type="object">Magento\Payment\Model\Checks\TotalMinMax</item>
<item name="zero_total" xsi:type="object">Magento\Payment\Model\Checks\ZeroTotal</item>
</argument>
</arguments>
</type>
there is a node having a name "mapping". Does anyone have any idea about its use?
I have read the question Magento 2 - What case I use di.xml and How to use di.xml for a module? and Alan storm's article "Magento 2 Object Manager Argument Replacement"
Thanks
Solution
When you check Magento\Payment\Model\Checks\SpecificationFactory
of the construt
public function __construct(\Magento\Payment\Model\Checks\CompositeFactory $compositeFactory, array $mapping)
{
$this->compositeFactory = $compositeFactory;
$this->mapping = $mapping;
}
Second argument array $mapping
in the array you will get all your argument which you defined in di.xml
EDIT
from the construct
$this->mapping
you will find all of the objects in the array which you defined in di.xml
.
For example If you set <argument name="mappingtest" xsi:type="array">
then you need to define construct
as
public function __construct(
\Magento\Payment\Model\Checks\CompositeFactory $compositeFactory, array $mappingytest
) {
$this->compositeFactory = $compositeFactory;
$this->mapping = $mapping;
}
Here $mappingytest
OTHER TIPS
The object manager injects the Magento\Core\Model\Url implementation class wherever there is a request for the Magento\Core\Model\UrlInterface in the global scope.
Multiple validation for different modules with filed.
<argument name="mapping" xsi:type="array">
<item name="country" xsi:type="object">Magento\Payment\Model\Checks\CanUseForCountry</item>
<item name="currency" xsi:type="object">Magento\Payment\Model\Checks\CanUseForCurrency</item>
<item name="checkout" xsi:type="object">Magento\Payment\Model\Checks\CanUseCheckout</item>
<item name="internal" xsi:type="object">Magento\Payment\Model\Checks\CanUseInternal</item>
<item name="total" xsi:type="object">Magento\Payment\Model\Checks\TotalMinMax</item>
<item name="zero_total" xsi:type="object">Magento\Payment\Model\Checks\ZeroTotal</item>
</argument>
Now check SpecificationFactory file for Business logic.
vendor/magento/module-payment/Model/Checks/SpecificationFactory.php
class SpecificationFactory
{
/**
* Composite Factory
*
* @var \Magento\Payment\Model\Checks\CompositeFactory
*/
protected $compositeFactory;
/**
* @var array
*/
protected $mapping;
/**
* Construct
*
* @param \Magento\Payment\Model\Checks\CompositeFactory $compositeFactory
* @param array $mapping
*/
public function __construct(\Magento\Payment\Model\Checks\CompositeFactory $compositeFactory, array $mapping)
{
$this->compositeFactory = $compositeFactory;
$this->mapping = $mapping;
}
/**
* Creates new instances of payment method models
*
* @param array $data
* @return Composite
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function create($data)
{
$specifications = array_intersect_key($this->mapping, array_flip((array)$data));
return $this->compositeFactory->create(['list' => $specifications]);
}
}
It validates the mapping data module wise.
$specifications = array_intersect_key($this->mapping, array_flip((array)$data));
Conclusion
The conversation with @Keyur Shah and the suggestion of @Jignesh Khunt conclude that you can add configurations in di.xml
and can access in type class here Magento\Payment\Model\Checks\SpecificationFactory
. In last param array $mapping
in below files constructor.
vendor\magento\module-payment\Model\Checks\SpecificationFactory.php
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Payment\Model\Checks;
/**
* Creates complex specification.
*
* Use this class to register predefined list of specifications that should be added to any complex specification.
*
* @api
* @since 100.0.2
*/
class SpecificationFactory
{
/**
* Composite Factory
*
* @var \Magento\Payment\Model\Checks\CompositeFactory
*/
protected $compositeFactory;
/**
* @var array
*/
protected $mapping;
/**
* Construct
*
* @param \Magento\Payment\Model\Checks\CompositeFactory $compositeFactory
* @param array $mapping
*/
public function __construct(\Magento\Payment\Model\Checks\CompositeFactory $compositeFactory, array $mapping)
{
$this->compositeFactory = $compositeFactory;
$this->mapping = $mapping;
}
/**
* Creates new instances of payment method models
*
* @param array $data
* @return Composite
* @throws \Magento\Framework\Exception\LocalizedException
*/
public function create($data)
{
$specifications = array_intersect_key($this->mapping, array_flip((array)$data));
return $this->compositeFactory->create(['list' => $specifications]);
}
}
The argument node (here "$mapping") must be member variable of the type class(Magento\Payment\Model\Checks\SpecificationFactory
).
Then the data you pass in di.xml
will be accessible and usable in your factory class and you can customize the logic. I have used to initialize dynamic class according to data available in $mapping array (without rewrite or plugin/prefrence) using this feature.