フィールドを含むフィールドセットを UI フォームに追加する簡単な方法

公開: 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,
        'Vendor_Product',
        __DIR__
    );
    ?>

composer ファイルを作成します (モジュールを転送する場合) app/code/Vendor/Module/composer.json :

 {
        "name": "vendor/module-product",
        "説明": "該当なし",
        "type": "magento2-module",
        "バージョン": "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">
        <module name="Vendor_Product" setup_version="1.0.0">
            <シーケンス>
                <モジュール名="Magento_Catalog"/>
            </シーケンス>
        </モジュール>
    </config>

次のように入力してモジュールを有効にします: bin/magento module:enable Vendor_Product および bin/magento setup:upgrade をルート Magento ディレクトリに入力します。

次に、モジュールの内容を追加します: 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>
                </アイテム>
            </引数>
        </引数>
    </virtualType>
</config>

修飾子は、データの追加と、要素および UI フォーム コンポーネントを使用した一部の操作を担当します。 モディファイアのインターフェイスから派生した 2 つの主要なメソッドがあります (常に存在する必要があります)。

 <?php
    /**
     * 著作権 2016 マジェント。 全著作権所有。
     * ライセンスの詳細については、COPYING.txt を参照してください。
     */
    名前空間 Magento\Ui\DataProvider\Modifier;
    
    /**
     * クラス ModifierInterface
     */
    インターフェイス ModifierInterface
    {
        /**
         * @param 配列 $data
         * @return 配列
         */
        public function modifyData(array $data);
    
        /**
         * @param 配列 $meta
         * @return 配列
         */
        public function modifyMeta(array $meta);
    }
    ?>

この例では、modifyMeta メソッドを使用します。 modifyData メソッドについては、次の記事で説明します。

ここで、製品編集ページ用のカスタム フィールドセットを含む修飾子ファイル (app/code/Vendor/Product/Ui/DataProvider/Product/Form/Modifier/CustomFieldset.php) を作成し、フィールドを入力します。

 <?php
namespace 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 = 'custom_fieldset';
    const CUSTOM_FIELDSET_CONTENT = 'custom_fieldset_content';
    const CONTAINER_HEADER_NAME = 'custom_fieldset_content_header';

    // フィールド名
    const FIELD_NAME_TEXT = 'example_text_field';
    const FIELD_NAME_SELECT = 'example_select_field';
    const FIELD_NAME_MULTISELECT = 'example_multiselect_field';

    /**
     * @var \Magento\Catalog\Model\Locator\LocatorInterface
     */
    保護された $locator;

    /**
     * @var ArrayManager
     */
    保護された $arrayManager;

    /**
     * @var URLInterface
     */
    保護された $urlBuilder;

    /**
     * @var 配列
     */
    保護された $meta = [];

    /**
     * @param LocatorInterface $locator
     * @param ArrayManager $arrayManager
     * @param UrlInterface $urlBuilder
     */
    パブリック関数 __construct(
        LocatorInterface $ロケータ、
        ArrayManager $arrayManager,
        URL インターフェース $urlBuilder
    ) {
        $this->locator = $locator;
        $this->arrayManager = $arrayManager;
        $this->urlBuilder = $urlBuilder;
    }

    /**
     * データ修飾子は、この例では何もしません。
     *
     * @param 配列 $data
     * @return 配列
     */
    public function modifyData(配列 $data)
    {
        $データを返します。
    }

    /**
     * メタデータ修飾子: 私たちのフィールドセットを追加します
     *
     * @param 配列 $meta
     * @return 配列
     */
    public function modifyMeta(配列 $meta)
    {
        $this->meta = $meta;
        $this->addCustomFieldset();

        $this->meta を返します。
    }

    /**
     * 既存のメタデータを私たちのメタデータとマージします (上書きしないでください!)
     *
     * @return void
     */
    保護された関数 addCustomFieldset()
    {
        $this->meta = array_merge_recursive(
            $this->メタ、
            [
                static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
            ]
        );
    }

    /**
     * 私たちのフィールドセット構成を宣言します
     *
     * @return 配列
     */
    保護された関数 getFieldsetConfig()
    {
        戻る [
            '引数' => [
                'データ' => [
                    '設定' => [
                        'ラベル' => __('フィールドセットのタイトル'),
                        'componentType' => フィールドセット::名前,
                        'dataScope' => static::DATA_SCOPE_PRODUCT, // 商品データにデータを保存
                        'プロバイダー' => static::DATA_SCOPE_PRODUCT . '_情報源'、
                        'ns' => static::FORM_NAME,
                        '折りたたみ可能' => true,
                        'sortOrder' => 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/フォーム/コンポーネント/複合',
                        'sortOrder' => $sortOrder,
                        'content' => __('ここに任意のテキストを記述できます'),
                    ]、
                ]、
            ]、
            '子供' => [],
        ];
    }

    /**
     * テキストフィールドの設定例
     *
     * @param $sortOrder
     * @return 配列
     */
    保護された関数 getTextFieldConfig($sortOrder)
    {
        戻る [
            '引数' => [
                'データ' => [
                    '設定' => [
                        'label' => __('サンプル テキスト フィールド'),
                        'formElement' => フィールド::名前,
                        'componentType' => 入力::名前,
                        'dataScope' => static::FIELD_NAME_TEXT,
                        'dataType' => 番号::名前、
                        'sortOrder' => $sortOrder,
                    ]、
                ]、
            ]、
        ];
    }

    /**
     * 選択フィールドの設定例
     *
     * @param $sortOrder
     * @return 配列
     */
    保護された関数 getSelectFieldConfig($sortOrder)
    {
        戻る [
            '引数' => [
                'データ' => [
                    '設定' => [
                        'ラベル' => __('オプション選択'),
                        'componentType' => フィールド::名前,
                        'formElement' => Select::NAME,
                        'dataScope' => static::FIELD_NAME_SELECT,
                        'dataType' => テキスト::名前、
                        'sortOrder' => $sortOrder,
                        'オプション' => $this->_getOptions(),
                        「目に見える」=>真、
                        「無効」 => false、
                    ]、
                ]、
            ]、
        ];
    }

    /**
     * 複数選択フィールド構成の例
     *
     * @param $sortOrder
     * @return 配列
     */
    保護された関数 getMultiSelectFieldConfig($sortOrder)
    {
        戻る [
            '引数' => [
                'データ' => [
                    '設定' => [
                        'label' => __('Options Multiselect'),
                        'componentType' => フィールド::名前,
                        'formElement' => MultiSelect::NAME,
                        'dataScope' => static::FIELD_NAME_MULTISELECT,
                        'dataType' => テキスト::名前、
                        'sortOrder' => $sortOrder,
                        'オプション' => $this->_getOptions(),
                        「目に見える」=>真、
                        「無効」 => false、
                    ]、
                ]、
            ]、
        ];
    }

    /**
     * オプション配列としてサンプル オプションを取得します。
     * [
     * ラベル => 文字列、
     * 値 => option_id
     * ]
     *
     * @return 配列
     */
    保護された関数 _getOptions()
    {
        $options = [
            1 => [
                'ラベル' => __('オプション 1'),
                '値' => 1
            ]、
            2 => [
                'ラベル' => __('オプション 2'),
                '値' => 2
            ]、
            3 => [
                'ラベル' => __('オプション 3'),
                '値' => 3
            ]、
        ];

        $オプションを返します。
    }
}
?>

この例では、既存の UI フォームのメタデータを取得して、新しいデータとマージする必要があります (書き換えではありません!)。

 <?php
/**
 * 既存のメタデータを私たちのメタデータとマージします (上書きしないでください!)
 *
 * @return void
 */
保護された関数 addCustomFieldset()
{
    $this->meta = array_merge_recursive(
        $this->メタ、
        [
            static::CUSTOM_FIELDSET_INDEX => $this->getFieldsetConfig(),
        ]
    );
}
?>

完了したら、新しいフィールドセットを getFieldsetConfig メソッドに追加します。

 <?php
/**
 * 私たちのフィールドセット構成を宣言します
 *
 * @return 配列
 */
保護された関数 getFieldsetConfig()
{
    戻る [
        '引数' => [
            'データ' => [
                '設定' => [
                    'ラベル' => __('フィールドセットのタイトル'),
                    'componentType' => フィールドセット::名前,
                    'dataScope' => static::DATA_SCOPE_PRODUCT, // 商品データにデータを保存
                    'プロバイダー' => static::DATA_SCOPE_PRODUCT . '_情報源'、
                    'ns' => static::FORM_NAME,
                    '折りたたみ可能' => true,
                    'sortOrder' => 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 オプションは主要なオプションの 1 つであり、コンポーネント タイプを担当します。 折りたたみ可能なオプションは、フィールドセットの折りたたみと展開を担当します。 open オプションは、フォームの描画中にデフォルトでフィールドセットを開くかどうかを定義します。

次に、getHeaderContainerConfig メソッドでヘッダーをフィールドセットに追加し、フィールドの 3 つの例: text、select、および multiselect を追加します。 ただし、modifyData メソッドにデータを追加するまで、製品とフォームはデータを受け取りません。 ただし、保存中にデータを送信および傍受する機能があります。

フォームがどのように見えるか見てみましょう:

データの保存は、メインの execute メソッドの製品コントローラー ファイル 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">
    <event name="catalog_product_save_after">
        <observer name="save_example_data" instance="Vendor\Product\Observer\ProductSaveAfter" />
    </イベント>
</config>

次に、インスタンス属性で指定したオブザーバーのクラスを作成します – app/code/Vendor/Product/Observer/ProductSaveAfter.php:

 <?php
名前空間ベンダー\製品\オブザーバー;

\Magento\Framework\Event\ObserverInterface を使用します。
\Magento\Framework\Event\Observer を EventObserver として使用します。
Vendor\Product\Ui\DataProvider\Product\Form\Modifier\CustomFieldset を使用します。

クラス ProductSaveAfter は ObserverInterface を実装します
{

    /**
     * @param EventObserver $observer
     */
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        /** @var \Magento\Catalog\Model\Product $product */
        $product = $observer->getEvent()->getProduct();
        if (!$製品) {
            戻る;
        }

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

        // ここでデータを操作します
    }
}
?>

オブザーバーのデータ:

これで、オブザーバーから独自のモデルを呼び出して、データを保存したり、必要に応じて変更したりできます。

気をつけて! モデルの保存が製品の保存に関連している場合、再帰につながる可能性があります。