UI-Form에 필드가 있는 Fieldset을 추가하는 쉬운 방법

게시 됨: 2016-08-23

이 기사에서는 제품 편집 UI 양식에 필드가 있는 필드 세트를 추가하는 간단한 모듈을 만들 것입니다. 또한 제품을 저장하는 동안 이 데이터를 가로채는 관찰자를 만들 것입니다.

먼저 Vendor_Product 모듈을 생성해야 합니다.

1. app/code/Vendor/Product 디렉토리 생성
2. 다음 내용으로 app/code/Vendor/Product/registration.php 등록 파일을 만듭니다.

 <?php
    \Magento\Framework\Component\ComponentRegistrar::register(
        \Magento\Framework\Component\ComponentRegistrar::MODULE,
        '공급업체_제품',
        __디렉터리__
    );
    ?>

컴포저 파일 생성(모듈을 전송하려는 경우) app/code/Vendor/Module/composer.json :

 {
        "이름": "공급업체/모듈 제품",
        "설명": "해당 사항 없음",
        "유형": "magento2 모듈",
        "버전": "1.0.0",
        "라이센스": [
            "OSL-3.0",
            "AFL-3.0"
        ],
        "자동 로드": {
            "파일": [
                "등록.php"
            ],
            "psr-4": {
                "공급업체\\제품\\": ""
            }
        }
    }

이제 Magento_Catalog 모듈의 종속성을 사용하여 모듈의 기본 XML 파일 app/code/Vendor/Product/etc/module.xml을 만듭니다. 모달 창이 해당 형식에 추가되기 때문입니다.

 <?xml 버전="1.0"?>
    <config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
        <모듈 이름="Vendor_Product" setup_version="1.0.0">
            <순서>
                <모듈 이름="Magento_Catalog"/>
            </순서>
        </모듈>
    </구성>

루트 Magento 디렉토리에 bin/magento module:enable Vendor_Product 및 bin/magento setup:upgrade를 입력하여 모듈을 활성화합니다.

그런 다음 모듈의 콘텐츠를 추가합니다. 추가할 UI 형식 메타데이터 및 가상 유형입니다.

app/code/Vendor/Product/etc/adminhtml/di.xml 파일을 만듭니다. 우리는 내부에 수정자를 배치할 것입니다:

 <?xml 버전="1.0"?>
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <virtualType name="Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\Pool">
        <인수>
            <argument name="modifiers" xsi:type="array">
                <item name="custom-fieldset" xsi:type="array">
                    <item name="class" xsi:type="string">Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset</item>
                    <item name="sortOrder" xsi:type="number">10</item>
                </항목>
            </인수>
        </인수>
    </가상 유형>
</구성>

수정자는 데이터 추가 및 요소 및 UI 형식 구성 요소에 대한 일부 조작을 담당합니다. 수정자의 인터페이스에서 가져온 두 가지 주요 메서드가 있습니다(항상 표시되어야 함).

 <?php
    /**
     * Copyright 2016 마젠토. 판권 소유.
     * 라이선스에 대한 자세한 내용은 COPYING.txt를 참조하십시오.
     */
    네임스페이스 Magento\Ui\DataProvider\Modifier;
    
    /**
     * 클래스 수정자 인터페이스
     */
    인터페이스 수정자인터페이스
    {
        /**
         * @param 배열 $data
         * @return 배열
         */
        공개 함수 modifyData(배열 $data);
    
        /**
         * @param 배열 $meta
         * @return 배열
         */
        공개 함수 modifyMeta(배열 $meta);
    }
    ?>

이 예제에서는 modifyMeta 메서드를 사용할 것입니다. modifyData 메서드는 다음 기사에서 설명합니다.

이제 제품 편집 페이지에 대한 사용자 정의 필드 세트가 있는 수정자 파일(app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php)을 만들고 필드로 채우십시오.

 <?php
네임스페이스 Vendor\Product\Ui\DataProvider\Product\Form\Modifier;

Magento\Catalog\Model\Locator\LocatorInterface를 사용하십시오.
Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier를 사용하십시오.
Magento\Framework\Stdlib\ArrayManager를 사용하십시오.
Magento\Framework\UrlInterface를 사용하십시오.
Magento\Ui\Component\Container를 사용하십시오.
Magento\Ui\Component\Form\Fieldset 사용;
Magento\Ui\Component\Form\Element\DataType\Number 사용;
Magento\Ui\Component\Form\Element\DataType\Text 사용;
Magento\Ui\Component\Form\Element\Input 사용;
Magento\Ui\Component\Form\Element\Select를 사용하십시오.
Magento\Ui\Component\Form\Element\MultiSelect 사용;
Magento\Ui\Component\Form\Field 사용;

클래스 CustomFieldset은 AbstractModifier를 확장합니다.
{

    // 컴포넌트 인덱스
    const CUSTOM_FIELDSET_INDEX = '커스텀_필드셋';
    const CUSTOM_FIELDSET_CONTENT = '맞춤_필드세트_콘텐츠';
    const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // 필드 이름
    const FIELD_NAME_TEXT = '예시_텍스트_필드';
    const FIELD_NAME_SELECT = 'example_select_field';
    const FIELD_NAME_MULTISELECT = 'example_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    보호된 $locator;

    /**
     * @var 어레이매니저
     */
    보호된 $arrayManager;

    /**
     * @var URL인터페이스
     */
    보호된 $urlBuilder;

    /**
     * @var 배열
     */
    보호된 $메타 = [];

    /**
     * @param LocatorInterface $locator
     * @param ArrayManager $arrayManager
     * @param UrlInterface $urlBuilder
     */
    공개 함수 __construct(
        로케이터 인터페이스 $ 로케이터,
        어레이매니저 $배열매니저,
        URL 인터페이스 $urlBuilder
    ) {
        $this->locator = $locator;
        $this->arrayManager = $arrayManager;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * 데이터 수정자는 이 예에서 아무 작업도 수행하지 않습니다.
     *
     * @param 배열 $data
     * @return 배열
     */
    공개 함수 modifyData(배열 $data)
    {
        $ 데이터 반환;
    }

    /**
     * 메타 데이터 수정자: 필드 세트 추가
     *
     * @param 배열 $meta
     * @return 배열
     */
    공개 함수 modifyMeta(배열 $meta)
    {
        $this->meta = $meta;
        $this->addCustomFieldset();

        $this->메타를 반환합니다.
    }

    /**
     * 기존 메타 데이터를 우리의 메타 데이터와 병합합니다(덮어쓰지 마십시오!)
     *
     * @반환 무효
     */
    보호된 함수 addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $this->메타,
            [
                static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * 우리의 fieldset 구성을 선언하십시오
     *
     * @return 배열
     */
    보호된 함수 getFieldsetConfig()
    {
        반품 [
            '인수' => [
                '데이터' => [
                    '구성' => [
                        '레이블' => __('필드셋 제목'),
                        'componentType' => Fieldset::NAME,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // 제품 데이터에 데이터 저장
                        '제공자' => static::DATA_SCOPE_PRODUCT . '_data_source',
                        'ns' => 정적::FORM_NAME,
                        '축소 가능' => 사실,
                        '정렬 순서' => 10,
                        '열림' => 사실,
                    ],
                ],
            ],
            '아이들' => [
                static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10),
                static::FIELD_NAME_TEXT => $this->getTextFieldConfig(20),
                static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30),
                static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40),
            ],
        ];
    }

    /**
     * 헤더 컨테이너에 대한 구성 가져오기
     *
     * @param int $sortOrder
     * @return 배열
     */
    보호된 함수 getHeaderContainerConfig($sortOrder)
    {
        반품 [
            '인수' => [
                '데이터' => [
                    '구성' => [
                        '레이블' => null,
                        'formElement' => 컨테이너::이름,
                        'componentType' => 컨테이너::이름,
                        '템플릿' => 'ui/form/components/complex',
                        'sortOrder' => $sortOrder,
                        'content' => __('여기에 아무 텍스트나 쓸 수 있습니다.'),
                    ],
                ],
            ],
            '어린이' => [],
        ];
    }

    /**
     * 예제 텍스트 필드 구성
     *
     * @param $sortOrder
     * @return 배열
     */
    보호된 함수 getTextFieldConfig($sortOrder)
    {
        반품 [
            '인수' => [
                '데이터' => [
                    '구성' => [
                        'label' => __('예제 텍스트 필드'),
                        'formElement' => 필드::이름,
                        'componentType' => 입력::이름,
                        'dataScope' => 정적::FIELD_NAME_TEXT,
                        'dataType' => 번호::이름,
                        'sortOrder' => $sortOrder,
                    ],
                ],
            ],
        ];
    }

    /**
     * 선택 필드 구성의 예
     *
     * @param $sortOrder
     * @return 배열
     */
    보호된 함수 getSelectFieldConfig($sortOrder)
    {
        반품 [
            '인수' => [
                '데이터' => [
                    '구성' => [
                        'label' => __('옵션 선택'),
                        'componentType' => 필드::이름,
                        'formElement' => 선택::이름,
                        'dataScope' => 정적::FIELD_NAME_SELECT,
                        'dataType' => 텍스트::이름,
                        'sortOrder' => $sortOrder,
                        '옵션' => $this->_getOptions(),
                        '보이는' => 사실,
                        '비활성화' => 거짓,
                    ],
                ],
            ],
        ];
    }

    /**
     * 다중 선택 필드 구성의 예
     *
     * @param $sortOrder
     * @return 배열
     */
    보호된 함수 getMultiSelectFieldConfig($sortOrder)
    {
        반품 [
            '인수' => [
                '데이터' => [
                    '구성' => [
                        'label' => __('옵션 다중 선택'),
                        'componentType' => 필드::이름,
                        'formElement' => 다중 선택::이름,
                        'dataScope' => 정적::FIELD_NAME_MULTISELECT,
                        'dataType' => 텍스트::이름,
                        'sortOrder' => $sortOrder,
                        '옵션' => $this->_getOptions(),
                        '보이는' => 사실,
                        '비활성화' => 거짓,
                    ],
                ],
            ],
        ];
    }

    /**
     * 예제 옵션을 옵션 배열로 가져오기:
     * [
     * 레이블 => 문자열,
     * 값 => option_id
     * ]
     *
     * @return 배열
     */
    보호된 함수 _getOptions()
    {
        $옵션 = [
            1 => [
                '레이블' => __('옵션 1'),
                '값' => 1
            ],
            2 => [
                '레이블' => __('옵션 2'),
                '값' => 2
            ],
            3 => [
                '레이블' => __('옵션 3'),
                '값' => 3
            ],
        ];

        $options를 반환합니다.
    }
}
?>

이 예에서는 기존 UI 형식 메타 데이터를 가져와 새 데이터와 병합(다시 작성하지 않음!)해야 합니다.

 <?php
/**
 * 기존 메타 데이터를 우리의 메타 데이터와 병합합니다(덮어쓰지 마십시오!)
 *
 * @반환 무효
 */
보호된 함수 addCustomFieldset()
{
    $this->meta = array_merge_recursive(
        $this->메타,
        [
            static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
        ]
    );
}
?>

완료되면 getFieldsetConfig 메소드에 새 필드 세트를 추가합니다.

 <?php
/**
 * 우리의 fieldset 구성을 선언하십시오
 *
 * @return 배열
 */
보호된 함수 getFieldsetConfig()
{
    반품 [
        '인수' => [
            '데이터' => [
                '구성' => [
                    '레이블' => __('필드셋 제목'),
                    'componentType' => Fieldset::NAME,
                    'dataScope' => static::DATA_SCOPE_PRODUCT, // 제품 데이터에 데이터 저장
                    '제공자' => static::DATA_SCOPE_PRODUCT . '_data_source',
                    'ns' => 정적::FORM_NAME,
                    '축소 가능' => 사실,
                    '정렬 순서' => 10,
                    '열림' => 사실,
                ],
            ],
        ],
        '아이들' => [
            static::CONTAINER_HEADER_NAME => $this->getHeaderContainerConfig(10),
            static::FIELD_NAME_TEXT => $this->getTextFieldConfig(20),
            static::FIELD_NAME_SELECT => $this->getSelectFieldConfig(30),
            static::FIELD_NAME_MULTISELECT => $this->getMultiSelectFieldConfig(40),
        ],
    ];
}
?>

추상 제품 UI 형식 수정자에서 상속하고 해당 네임스페이스와 데이터를 공급자로 사용합니다. 'provider' => static::DATA_SCOPE_PRODUCT . '_data_source'(여기서 DATA_SCOPE_PRODUCT는 'data.product' 라인임).

componentType 옵션은 주요 옵션 중 하나이며 구성 요소 유형을 담당합니다. 접을 수 있는 옵션은 필드 집합을 접고 확장하는 역할을 합니다. 그리고 열기 옵션은 양식을 그리는 동안 기본적으로 필드 세트를 열 것인지 여부를 정의합니다.

그런 다음 결과적으로 getHeaderContainerConfig 메소드의 필드 세트에 헤더를 추가하고 필드의 3가지 예(텍스트, 선택 및 다중 선택)를 추가합니다. 그러나 제품과 양식은 modifyData 메서드에 추가할 때까지 데이터를 수신하지 않습니다. 그러나 저장하는 동안 데이터를 전송하고 가로챌 수 있는 기능이 있습니다.

양식이 어떻게 보이는지 봅시다.

데이터 저장은 메인 실행 메소드의 제품 컨트롤러 파일 vendor/magento/module-catalog/Controller/Adminhtml/Product/Save.php 내에서 발생합니다. 모든 것이 올바른 방식으로 수행되면 이 메서드의 입력 데이터에 데이터가 올바르게 표시됩니다.

제품에 처음부터 해당 속성이 없으면 수동으로 저장해야 합니다. 관찰자에서 이 작업을 수행할 수 있습니다.

먼저 app/code/Vendor/Product/etc/adminhtml/events.xml 파일에서 선언합니다(프론트 엔드에 양식이 없기 때문에 adminhtml 범위를 사용합니다).

 <?xml 버전="1.0"?>
<config xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <이벤트 이름="catalog_product_save_after">
        <관찰자 이름="save_example_data" instance="Vendor\Product\Observer\ProductSaveAfter" />
    </이벤트>
</구성>

그런 다음 instance 속성에서 가리킨 관찰자의 클래스를 만듭니다. app/code/Vendor/Product/Observer/ProductSaveAfter.php:

 <?php
네임스페이스 Vendor\Product\Observer;

\Magento\Framework\Event\ObserverInterface를 사용하십시오.
\Magento\Framework\Event\Observer를 EventObserver로 사용하십시오.
Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset 사용;

ProductSaveAfter 클래스는 ObserverInterface를 구현합니다.
{

    /**
     * @param EventObserver $옵저버
     */
    공개 함수 실행(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        if (!$product) {
            반품;
        }

        $exampleTextField = $product->getData(CustomFieldset::FIELD_NAME_TEXT);
        $exampleSelectField = $product->getData(CustomFieldset::FIELD_NAME_SELECT);
        $exampleMultiSelectField = $product->getData(CustomFieldset::FIELD_NAME_MULTISELECT);

        // 여기에서 데이터 조작
    }
}
?>

관찰자의 데이터:

이제 관찰자로부터 자신의 모델을 호출하고 데이터를 저장하거나 원하는 대로 수정할 수 있습니다.

조심하세요! 모델 저장이 제품 저장과 연결되면 재귀로 이어질 수 있습니다.