DynamicRows (atau Associative Array) di Magento 2 REST API

Oct 02 2020

Saya menggunakan Magento 2 REST API untuk aplikasi seluler. Saya menghadapi beberapa kerumitan jadi saya butuh bantuan Anda.

Saya memiliki komponen DynamicRows dengan dua bidang dalam Formulir UI, nama bidang tersebut adalah pelokalan .

<container name="localization" sortOrder="9" >
    <argument name="data" xsi:type="array">
        <item name="config" xsi:type="array">
            <item name="component" xsi:type="string">Magento_Ui/js/dynamic-rows/dynamic-rows</item>
            <item name="template" xsi:type="string">ui/dynamic-rows/templates/default</item>
            <item name="componentType" xsi:type="string">dynamicRows</item>
            <item name="label" xsi:type="string" translate="true">Data</item>
            <item name="recordTemplate" xsi:type="string">record</item>
            <item name="addButtonLabel" xsi:type="string">Add Parameter</item>
            <item name="deleteProperty" xsi:type="boolean">false</item>
            <item name="enabled" xsi:type="boolean">false</item>
        </item>
    </argument>

    <container name="record">
        <argument name="data" xsi:type="array">
            <item name="config" xsi:type="array">
                <item name="label" xsi:type="string" translate="true" />
                <item name="component" xsi:type="string" translate="true">Magento_Ui/js/dynamic-rows/record</item>
                <item name="isTemplate" xsi:type="boolean">true</item>
                <item name="is_collection" xsi:type="boolean">true</item>
                <item name="showFallbackReset" xsi:type="boolean">false</item>
            </item>
        </argument>

        <field name="option_label">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Parameter</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="dataScope" xsi:type="string">option_label</item>
                    <item name="showFallbackReset" xsi:type="boolean">false</item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                    <item name="sortOrder" xsi:type="string">10</item>
                </item>
            </argument>
        </field>

        <field name="option_value">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="label" xsi:type="string" translate="true">Value</item>
                    <item name="formElement" xsi:type="string">input</item>
                    <item name="dataScope" xsi:type="string">option_value</item>
                    <item name="showFallbackReset" xsi:type="boolean">false</item>
                    <item name="additionalClasses" xsi:type="array">
                        <item name="cirklestudio_color_picker" xsi:type="boolean">true</item>
                    </item>
                    <item name="validation" xsi:type="array">
                        <item name="required-entry" xsi:type="boolean">true</item>
                    </item>
                    <item name="sortOrder" xsi:type="string">20</item>
                </item>
            </argument>
        </field>

        <actionDelete>
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="componentType" xsi:type="string">actionDelete</item>
                    <item name="dataType" xsi:type="string">text</item>
                    <item name="fit" xsi:type="boolean">false</item>
                    <item name="label" xsi:type="string" />
                    <item name="additionalClasses" xsi:type="string">data-grid-actions-cell</item>
                    <item name="template" xsi:type="string">Magento_Backend/dynamic-rows/cells/action-delete</item>
                </item>
            </argument>
        </actionDelete>
        
    </container>

</container>

Output dari DynamicRows ada di bawah

Array
(
    [0] => Array
        (
            [row_id] => 
            [option_label] => tmp_dir
            [option_value] => temp
            [position] => 1
            [record_id] => 0
            [initialize] => true
        )

    [1] => Array
        (
            [record_id] => 1
            [row_id] => 
            [option_label] => main_dir
            [option_value] => APD
            [position] => 2
            [initialize] => true
        )
)

Saya telah mendeklarasikan metode getLocalization () di Antarmuka saya

/**
 * Return localized parameters for the application
 *
 * @return mixed[]
 */
public function getLocalization();

Kemudian saya telah menerapkan metode tersebut

/**
 * @inheritdoc
 */
public function getLocalization()
{
    // Unserialize array
    $data = $this->_getData('localization') ? unserialize($this->_getData('localization')) : ""; $output = [];
    foreach ($data as $param) {
        $output[$param['option_label']] =  $param['option_value']; } return $output;
}

Dalam metode di atas, saya telah menyempurnakan output array DynamicRows sesuai persyaratan.

Array
(
    [tmp_dir] => temp
    [main_dir] => APD
)

Ketika saya mencapai titik akhir REST API, saya mendapatkan respons berikut.

<localization>
    <item>temp</item>
    <item>APD</item>
</localization>

Padahal saya mengharapkan tanggapan sebagai berikut

<localization>
    <tmp_dir>temp</tmp_dir>
    <main_dir>APD</main_dir>
</localization>

Saya telah mencari di sekitar artikel yang berbeda tetapi tidak dapat menemukan jawaban terbaik yang sesuai dengan kebutuhan saya.

Pertanyaan: Bagaimana saya akan mendapatkan hasil saya diharapkan menjaga hal ini dalam pikiran bahwa DynamicRows data yang tidak akan selalu sama, mungkin rekor lain memiliki lebih dari dua bidang dengan berbagai option_label dan option_value' ?

Jawaban

4 HerveTribouilloy Oct 03 2020 at 19:52

Saya telah berhasil menemukan yang berikut:

Saya pikir Anda akan berjuang untuk mendapatkan lebih banyak darinya. Pada dasarnya, kunci item memang berasal dari metode parsing inti Magento sehingga hasil Anda datang kepada Anda sebagai xml.

Saya dapat merinci langkah-langkah saya tetapi jumlahnya mencapai 2 antarmuka lagi dan sedikit parsing .. Beri tahu saya jika keluaran ini adalah sesuatu yang dapat Anda kompromi.

Jawaban Joseph lebih sederhana dari saya (lebih elegan). Tetapi di bawah ini adalah inti dari solusi saya. Saya juga memasang tautan ke repositori bitbucket untuk Anda coba sendiri.https://bitbucket.org/magstaging/apiparser/src/master/

    $output = []; foreach ($data as $param) { $output[$param['option_label']] = $param['option_value'];
            }
    
            return $this->parsedDataInterfaceFactory->create([ 'itemsData' => $output
            ]);


class ParsedResult implements ParsedDataInterface
{
    /**
     * @var \Mbs\Calculator\Api\Data\ParsedDataItemInterface[]
     */
    private $items = []; /** * OperationResult constructor. * @param array $itemsData
     * @param \Mbs\Calculator\Api\Data\ParsedDataItemInterfaceFactory $dataItemInterfaceFactory */ public function __construct( $itemsData,
        \Mbs\Calculator\Api\Data\ParsedDataItemInterfaceFactory $dataItemInterfaceFactory ) { foreach ($itemsData as $itemLabel => $itemValue) {
            $this->items[] = $dataItemInterfaceFactory->create([
                'label' => $itemLabel, 'value' => $itemValue
            ]);
        }
    }

    /**
     * @return \Mbs\Calculator\Api\Data\ParsedDataItemInterface[]
     */
    public function getLocalization()
    {
        return $this->items; } } class Item implements ParsedDataItemInterface { /** * @var string */ private $label;

    /**
     * @var string
     */
    private $value; /** * @inheritdoc */ public function __construct( string $label,
        string $value ) { $this->label = $label; $this->value = $value; } /** * @inheritdoc */ public function getLabel() { return $this->label;
    }

    /**
     * @inheritdoc
     */
    public function getValue()
    {
        return $this->value;
    }
}
2 JosephatSwiftOtter Oct 03 2020 at 20:38

Untuk mendapatkan hasil yang diinginkan, Anda perlu membuat lebih banyak kelas.

Dalam hal ini, getLocalizationharus mengembalikan sebuah instance dari kelas, seperti:

/**
 * @return \MyCompany\MyModule\Model\Localization[]
 **/
public function getLocalization(): array
{
    // Unserialize array
    $data = $this->_getData('localization') ? unserialize($this->_getData('localization')) : ""; return array_map(function($option) {
        return $this->localizationFactory->create([ 'label' => $param['option_label'],
            'value' => $param['option_value']
        ]);
    });
}

Dimana $this->localizationFactoryadalah: \MyCompany\MyModule\Model\LocalizationFactory.

LocalizationFactory harus memiliki dua metode:

  • getLabel
  • getValue

Ini mungkin tampak bertele-tele, dan memang begitu. Namun, rute ini memberi Anda kontrol 100% atas output. Testabilitas adalah bonus.