DynamicRows (หรือ Associative Array) ใน Magento 2 REST API

Oct 02 2020

ฉันใช้ Magento 2 REST API สำหรับแอปพลิเคชันมือถือ ฉันกำลังเผชิญกับความซับซ้อนดังนั้นฉันจึงต้องการความช่วยเหลือจากคุณ

ฉันมี DynamicRows องค์ประกอบที่มีสองเขตข้อมูลในแบบฟอร์ม UI ชื่อของสนามคือการแปล

<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>

ผลลัพธ์ของ DynamicRows อยู่ด้านล่าง

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
        )
)

ฉันได้ประกาศเมธอด getLocalization () ในอินเทอร์เฟซของฉัน

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

จากนั้นฉันได้ใช้วิธีการ

/**
 * @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;
}

ในวิธีการข้างต้นฉันได้ปรับแต่งเอาต์พุตอาร์เรย์ DynamicRows ตามข้อกำหนด

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

เมื่อฉันเข้าสู่จุดสิ้นสุด REST API ฉันจะได้รับคำตอบดังต่อไปนี้

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

ในขณะที่ฉันคาดหวังการตอบสนองต่อไปนี้

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

ฉันได้ค้นหาบทความต่างๆแล้ว แต่ไม่พบคำตอบที่ดีที่สุดที่เหมาะกับความต้องการของฉัน

คำถาม:ฉันจะได้รับผลที่คาดหวังของฉันรักษาสิ่งนี้ไว้ในใจว่าข้อมูล DynamicRows จะไม่เสมอกันอาจจะบันทึกอีกมีมากกว่าสองเขตข้อมูลที่มีแตกต่างกันoption_labelและoption_value ?

คำตอบ

4 HerveTribouilloy Oct 03 2020 at 19:52

ฉันได้จัดการสิ่งต่อไปนี้:

ฉันคิดว่าคุณจะต้องดิ้นรนเพื่อให้ได้มามากกว่านี้ โดยทั่วไปคีย์รายการมาจากวิธีการแยกวิเคราะห์แกน Magento เพื่อให้ผลลัพธ์ของคุณมาเป็น xml

ฉันสามารถบอกรายละเอียดขั้นตอนของฉันได้ แต่มันมีจำนวนถึง 2 อินเทอร์เฟซและการแยกวิเคราะห์เล็กน้อย .. โปรดแจ้งให้เราทราบว่าผลลัพธ์นี้เป็นสิ่งที่คุณสามารถประนีประนอมได้หรือไม่

คำตอบของโจเซฟนั้นง่ายกว่าของฉัน (สวยหรูกว่า) แต่ด้านล่างเป็นแกนหลักจากการแก้ปัญหาของฉัน ฉันยังใส่ลิงค์ไปยังที่เก็บ bitbucket เพื่อให้คุณทดลองใช้ด้วยตัวเอง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

เพื่อให้ได้ผลลัพธ์ที่ต้องการคุณต้องสร้างคลาสเพิ่มเติม

ในกรณีนี้getLocalizationควรส่งคืนอินสแตนซ์ของคลาสเช่น:

/**
 * @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']
        ]);
    });
}

อยู่ที่ไหน$this->localizationFactory: \MyCompany\MyModule\Model\LocalizationFactory.

LocalizationFactory ควรมีสองวิธี:

  • getLabel
  • getValue

สิ่งนี้อาจดูเหมือนละเอียดและเป็นเช่นนั้น อย่างไรก็ตามเส้นทางนี้ให้คุณควบคุมเอาต์พุตได้ 100% ความสามารถในการทดสอบเป็นโบนัส