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.