Magento 2'de birleştirilen modüllerde özel bir XML dosyasını nasıl alabilirim? (MageStackDay gizem soru 2)


22

500pts Bounty için MageStackDay bonus sorusu VE bir yıl boyunca ücretsiz Z-Ray lisansı kazanma imkanı. Daha fazla bilgi bulunabilir >> burada <<

Sorular Magento 2 ana geliştiricisi Anton Kril tarafından sağlandı / ilham alındı.

Soru:

Ayrı bir yapılandırma kümesi olan bir uzantı oluşturuyorum.
Bu, magento'nun sahip olduğu config.xmlveya routes.xmlveya fieldset.xmlveya başka bir yapılandırma xml dosyasını kullanamayacağım anlamına gelir .
Örnek.

Diyelim ki, sütun satırları olan bir 'tablo' yapılandırması tanımlıyorum. Bu xml'i aşağıda kullanabilirim. (ara 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>

Ancak, başka bir uzantı içeriyorsa table.xml, config okuyucu tarafından alınmasını istiyorum ve 2 veya daha fazla xml dosyası birleştirilmelidir. Yani ikinci dosya böyle gözüküyorsa

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

Sonuç, ikinci sütunun ilk satıra eklenmesi ve bunun değerinin attr1ikinci xml tarafından yazılmasıdır:

<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’de bunu sadece arayarak yapabilirdim.

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

Magento 2 için nasıl aynı şeyi yapabilirim?

Yanıtlar:


15

Magento 2'de bu \Magento\Framework\Config\Reader\Filesystemsınıf tarafından gerçekleştirilir . Bu sınıf, birleştirmek istediğiniz xml dosyasını belirtmenizi sağlar.

Aşağıdaki bölüm, mevcut modüllerde bulunan tüm dosyaları birleştirecek ve çıktıyı birleştirecektir (snippet from \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;
}

Oluşturduğum çözümde yukarıdaki sınıf gerekli xml dosyasını sağlamak ve doğrulamak için xsd dosyasının nerede bulunabileceğini belirtmek için genişletildi ( tam örnek için https://github.com/Genmato/MageStackTable adresine bakın ):

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
        );
    }

Birleştirilmiş verileri almak için daha sonra arayabilirsiniz:

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

Çıktı daha sonra birleştirilmiş xml dizisinin gösterimidir.

DÜZENLE:

Dosyaların okunma şeklini test etmek için çalışan bir örnek oluşturdum (bkz. Https://github.com/Genmato/MageStackTable ). Çözüm derlemesiyle yanıt güncellendi.


Vladimir, bugün erken saatlerde önceki cevap versiyonunu Domsınıf örneği ile gördüm . ReaderSınıf kullanarak cevap üzerinde çalışmaya başladım . Bu arada soru sayfasını yeniledik ve bunu yaptığınızı anladım :-) +1
Wojtek Naruniec

Tam ayrıntılı cevap ve github gelen POC modülü için teşekkürler. Lütfen gelecekteki referanslar için orada bırakın. Burada ... biraz ödül al.
Marius

Marius, teşekkürler! Modülü GitHub'da kullanılabilir kılar.
Vladimir Kerkhoff
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.