कैसे मैं एक कस्टम XML फ़ाइल को Magento 2 में एक के रूप में विलय कर सकता हूं? (MageStackDay रहस्य प्रश्न 2)


22

500 के लिए MageStackDay बोनस सवाल बाउंटी और एक साल के लिए मुफ्त जेड-रे लाइसेंस जीतने की संभावना है। अधिक जानकारी यहाँ पाई जा सकती है >> <<

मैजेंटो 2 कोर डेवलपर एंटोन क्रिल द्वारा प्रश्न प्रदान / प्रेरित किए गए हैं।

सवाल:

मैं एक एक्सटेंशन बना रहा हूं जिसमें कॉन्फ़िगरेशन का एक अलग सेट है।
इस का मतलब है मैं उपयोग नहीं कर सकते config.xmlया routes.xmlया fieldset.xmlया किसी अन्य config एक्सएमएल फ़ाइलें है Magento।
उदाहरण।

मान लीजिए कि मैं एक 'तालिका' कॉन्फिगर को परिभाषित कर रहा हूं जिसमें एक कॉलम है। मैं नीचे इस xml का उपयोग कर सकता हूं। (इसे कॉल करें table.xml)

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="path/to/table.xsd">
    <row id="row1">
        <column id="col1" sort="10" attr1="val1">
            <label>Col 1</label>
        </column>
    </row>
    <row id="row2">
        <column id="col1" sort="10" attr1="val1">
            <label>Col 1</label>
        </column>
        <column id="col2" sort="20" disabled="true" attr1="val2" >
            <label>Col 2</label>
        </column>
        <column id="col3" sort="15" attr1="val1">
            <label>Col 3</label>
        </column>
    </row>
</table>

लेकिन अगर किसी अन्य एक्सटेंशन में table.xmlमैं चाहता हूं कि इसे कॉन्फिग रीडर द्वारा उठाया जाए और 2 या अधिक xml फाइलों को मर्ज किया जाए। मेरा मतलब है कि अगर दूसरी फ़ाइल इस तरह दिखती है

<table xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="path/to/table.xsd">
    <row id="row1">
        <column id="col2" sort="10" attr1="val2">
            <label>Col 2</label>
        </column>
    </row>
    <row id="row2">
        <column id="col1" sort="10" attr1="val5" />
    </row>
</table>

इसका परिणाम यह होगा कि दूसरी पंक्ति को पहली पंक्ति में जोड़ा जाता है और attr1दूसरी xml द्वारा मान को अधिलेखित कर दिया जाता है:

<table ....>
    <row id="row1">
        <column id="col1" sort="10" attr1="val1"> <!-- from first xml -->
            <label>Col 1</label>
        </column>
        <column id="col2" sort="10" attr1="val2"><!-- from second xml-->
            <label>Col 2</label>
        </column>
    </row>
    <row id="row2">
        <column id="col1" sort="10" attr1="val5"><!--they apear in both xmls with the same path and id and second one overrides the value for `attr1`-->
            <label>Col 1</label>
        </column>
        <column id="col2" sort="20" disabled="true" attr1="val2"><!-- from first xml -->
            <label>Col 2</label>
        </column>
        <column id="col3" sort="15" attr1="val1"><!-- from first xml -->
            <label>Col 3</label>
        </column>
    </row>
</table>

Magento 1 में मैं सिर्फ कॉल करके ऐसा कर सकता था

 $merged = Mage::getConfig()->loadModulesConfiguration('table.xml')
            ->applyExtends();

मैं Magento 2 के लिए समान कैसे कर सकता हूं?

जवाबों:


15

Magento 2 में इसे \Magento\Framework\Config\Reader\Filesystemकक्षा द्वारा नियंत्रित किया जाता है । यह वर्ग आपको एक्सएमएल फ़ाइल को निर्दिष्ट करने की अनुमति देता है जिसे आप मर्ज करना चाहते हैं।

निम्न भाग उपलब्ध मॉड्यूल में पाई गई सभी फाइलों को मर्ज कर आउटपुट (स्निपेट से \Magento\Framework\Config\Reader\Filesystem) को मर्ज करेगा

/**
 * Load configuration scope
 *
 * @param string|null $scope
 * @return array
 */
public function read($scope = null)
{
    $scope = $scope ?: $this->_defaultScope;
    $fileList = $this->_fileResolver->get($this->_fileName, $scope);
    if (!count($fileList)) {
        return [];
    }
    $output = $this->_readFiles($fileList);

    return $output;
}

/**
 * Read configuration files
 *
 * @param array $fileList
 * @return array
 * @throws \Magento\Framework\Exception
 */
protected function _readFiles($fileList)
{
    /** @var \Magento\Framework\Config\Dom $configMerger */
    $configMerger = null;
    foreach ($fileList as $key => $content) {
        try {
            if (!$configMerger) {
                $configMerger = $this->_createConfigMerger($this->_domDocumentClass, $content);
            } else {
                $configMerger->merge($content);
            }
        } catch (\Magento\Framework\Config\Dom\ValidationException $e) {
            throw new \Magento\Framework\Exception("Invalid XML in file " . $key . ":\n" . $e->getMessage());
        }
    }
    if ($this->_isValidated) {
        $errors = [];
        if ($configMerger && !$configMerger->validate($this->_schemaFile, $errors)) {
            $message = "Invalid Document \n";
            throw new \Magento\Framework\Exception($message . implode("\n", $errors));
        }
    }

    $output = [];
    if ($configMerger) {
        $output = $this->_converter->convert($configMerger->getDom());
    }
    return $output;
}

समाधान में मैंने ऊपर जो वर्ग बनाया है, उसे आवश्यक xml फ़ाइल की आपूर्ति करने के लिए बढ़ाया गया है और निर्दिष्ट करें कि xsd फ़ाइल को मान्य करने के लिए कहाँ पाया जा सकता है (देखें https://github.com/Genmato/MageStackTable पूर्ण उदाहरण के लिए):

namespace Genmato\TableXml\Model\Table;

class Reader extends \Magento\Framework\Config\Reader\Filesystem
{
    protected $_idAttributes = [
        '/table/row' => 'id',
        '/table/row/column' => 'id',
    ];

    /**
     * @param \Magento\Framework\Config\FileResolverInterface $fileResolver
     * @param \Magento\Framework\Config\ConverterInterface $converter
     * @param \Genmato\TableXml\Model\Table\SchemaLocator $schemaLocator
     * @param \Magento\Framework\Config\ValidationStateInterface $validationState
     * @param string $fileName
     * @param array $idAttributes
     * @param string $domDocumentClass
     * @param string $defaultScope
     */
    public function __construct(
        \Magento\Framework\Config\FileResolverInterface $fileResolver,
        \Magento\Framework\Config\ConverterInterface $converter,
        \Genmato\TableXml\Model\Table\SchemaLocator $schemaLocator,
        \Magento\Framework\Config\ValidationStateInterface $validationState,
        $fileName = 'table.xml',
        $idAttributes = [],
        $domDocumentClass = 'Magento\Framework\Config\Dom',
        $defaultScope = 'global'
    ) {
        parent::__construct(
            $fileResolver,
            $converter,
            $schemaLocator,
            $validationState,
            $fileName,
            $idAttributes,
            $domDocumentClass,
            $defaultScope
        );
    }

मर्ज किए गए डेटा को प्राप्त करने के लिए आप फिर कॉल कर सकते हैं:

$output = $this->_objectManager->get('Genmato\TableXml\Model\Table\Reader')->read();

आउटपुट तब मर्ज किए गए xml का एक सरणी प्रतिनिधित्व है।

संपादित करें:

फ़ाइलों को पढ़ने के तरीके का परीक्षण करने के लिए मैंने एक कार्यशील उदाहरण बनाया (देखें https://github.com/Genmato/MageStackTable )। समाधान बिल्ड के साथ उत्तर अपडेट करें।


व्लादिमीर, पहले आज मैंने आपके पिछले उत्तर संस्करण को Domकक्षा उदाहरण के साथ देखा । मैंने उत्तर Readerवर्ग के उपयोग पर काम करना शुरू कर दिया । इस बीच मैंने प्रश्न पृष्ठ को रीफ्रेश किया और महसूस किया कि आपने :-) +1
वोजटेक नारुनीक

पूर्ण विस्तृत उत्तर के लिए और Github से POC मॉड्यूल के लिए धन्यवाद। कृपया इसे भविष्य के संदर्भों के लिए वहीं छोड़ दें। यहाँ ... कुछ इनाम है।
मेरियस

Marius, धन्यवाद! GitHub पर उपलब्ध मॉड्यूल को छोड़ देगा।
व्लादिमीर केर्खॉफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.