Magento 2에서 하나로 병합 된 모듈에서 사용자 지정 XML 파일을 만들려면 어떻게해야합니까? (MageStackDay 미스터리 질문 2)


22

500pts Bounty에 대한 MageStackDay 보너스 질문 및 1 년간 무료 Z-Ray 라이센스 획득 가능성. 자세한 내용은 여기를 참조하십시오 >> 여기 <<

질문은 Magento 2의 핵심 개발자 인 Anton Kril이 제공하고 영감을 얻었습니다.

의문:

별도의 구성 집합을 가진 확장을 만들고 있습니다.
이 방법은 내가 사용할 수 없습니다 config.xml또는 routes.xml또는 fieldset.xml또는이 젠토 다른 구성 xml 파일.
예.

행에 열이있는 '테이블'구성을 정의한다고 가정 해 봅시다. 아래에서이 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

마 젠토 2에서는 \Magento\Framework\Config\Reader\Filesystem클래스에 의해 처리됩니다 . 이 클래스를 사용하면 병합하려는 xml 파일을 지정할 수 있습니다.

다음 부분은 모든 파일이 가능한 모듈에서 발견 병합하고 출력을 병합합니다 (니펫 \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했다 실현
— 보이 테크 Naruniec

자세한 답변과 github의 POC 모듈에 감사드립니다. 나중에 참조 할 수 있도록 남겨 두십시오. 여기에 ... 현상금이 있습니다.
— Marius

마리우스, 고마워! GitHub에서 모듈을 사용 가능한 상태로 둡니다.
— 블라디미르 Kerkhoff
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.