1

I'm working in Magento 2.2.5.

Basically, I have created a custom product attribute serilized_data with text as backend_type by using below file and want to save custom options of product in this attribute by serializing it.

app\code\Vendor\Module\Setup\InstallData.php

<?php

namespace Vendor\Module\Setup;

use Magento\Framework\Setup\InstallDataInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Catalog\Setup\CategorySetupFactory;

/**
 * @codeCoverageIgnore
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class InstallData implements InstallDataInterface
{
    /**
     * Eav setup factory
     * @var EavSetupFactory
     */
    private $eavSetupFactory;

    /**
     * Init
     * @param EavSetupFactory $eavSetupFactory
     */
    public function __construct(\Magento\Eav\Setup\EavSetupFactory $eavSetupFactory)
    {
        $this->eavSetupFactory = $eavSetupFactory;
    }

    /**
     * {@inheritdoc}
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
     * @SuppressWarnings(PHPMD.NPathComplexity)
     */
    public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context)
    {
        $installer = $setup;
        $installer->startSetup();
        $this->installEntities($setup);
        $installer->endSetup(); 
    }

    /**
     * Default entites and attributes
     *
     * @param array|null $entities
     * @return array
     *
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function installEntities($setup)
    {
        $attributes = [
            'is_serialized_data'       => [
                'type'                       => 'int',
                'label'                      => 'Add Serialize Data',
                'input'                      => 'select',
                'source'                     => 'Magento\Eav\Model\Entity\Attribute\Source\Boolean',
                'required'                   => false,
                'note'                       =>
                    'This data will save in sigle attribute serilized_data.',
                'sort_order'                 => 1,
                'apply_to'                   => 'simple,virtual',
                'is_configurable'            => false,
                'group'                      => 'Serialized Data',
            ],
            'serilized_data'  => [
                'type'                       => 'text',
                'label'                      => 'Serialize Data',
                'input'                      => 'text',
                'backend'                    => 'Vendor\Module\Model\Product\Attribute\Backend\Customserializeddata',
                'required'                   => false,
                'sort_order'                 => 2,
                'apply_to'                   => 'simple,virtual,configurable',
                'is_configurable'            => false,
                'group'                      => 'Serialize Data',
            ]
        ];

        $eavSetup = $this->eavSetupFactory->create();
        foreach ($attributes as $attrCode => $attr) {
            $eavSetup->addAttribute('catalog_product', $attrCode, $attr);
        }

        $entityTypeId = $eavSetup->getEntityTypeId(\Magento\Catalog\Model\Product::ENTITY);
        $attributeSetId = $eavSetup->getAttributeSetId($entityTypeId, 'Default');

        $groupName = 'Serialize Data';
        $eavSetup->updateAttributeGroup($entityTypeId, $attributeSetId, $groupName, 'sort_order', 41);
        $eavSetup->updateAttributeGroup($entityTypeId, $attributeSetId, $groupName, 'attribute_group_code', 'serialize-data');
        $eavSetup->updateAttributeGroup($entityTypeId, $attributeSetId, $groupName, 'tab_group_code', 'advanced');

        $eavSetup->addAttributeToGroup($entityTypeId, $attributeSetId, $groupName, 'is_serialized_data');
        $eavSetup->addAttributeToGroup($entityTypeId, $attributeSetId, $groupName, 'serilized_data');

        $connection = $setup->getConnection();
        $adminRuleTable = $setup->getTable('authorization_rule');
        $connection->update(
            $adminRuleTable,
            array('resource_id' => 'Vendor_Module::serilized_data'),
            array('resource_id = ?' => 'Magento_Sales::serilized_data')
        );

    }
}

Then I have created the form fields using product_form.xml using UI-components.

app\code\Vendor\Module\view\adminhtml\ui_component\product_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
   <fieldset name="serialize-data">
        <fieldset name="fieldset_test" sortOrder="10">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="scopeLabel" xsi:type="string">[GLOBAL]</item>
                </item>
            </argument>
            <settings>
                <label translate="true"/>
            </settings>
            <container>
                <field name="field_1" sortOrder="10" formElement="select">
                    <argument name="data" xsi:type="array">
                        <item name="config" xsi:type="array">
                            <item name="rawOptions" xsi:type="boolean">true</item>
                        </item>
                    </argument>
                    <settings>
                        <scopeLabel>[GLOBAL]</scopeLabel>
                        <label translate="true">Product Can Has Serialize Data</label>
                        <dataScope>field_1</dataScope>
                        <imports>
                            <link name="visible">${$.provider}:data.product.is_serialized_data</link>
                        </imports>
                    </settings>
                    <formElements>
                        <select>
                            <settings>
                                <options class="Magento\Config\Model\Config\Source\Yesno"/>
                            </settings>
                        </select>
                    </formElements>
                </field>
                <field name="field_2" sortOrder="20" formElement="input">
                    <settings>
                        <scopeLabel>[GLOBAL]</scopeLabel>
                        <label translate="true">Test Data</label>
                        <notice translate="true">Text Input going save as serialize-data/json data in serilized_data product's attribute attribute.</notice>
                        <dataScope>field_2</dataScope>
                        <imports>
                            <link name="visible">${$.provider}:data.product.is_serialized_data</link>
                        </imports>
                    </settings>
                </field>
            </container>
        </fieldset>
    </fieldset>
</form>

And the backend model for attribute is

Vendor\Module\Model\Product\Attribute\Backend\Customserializeddata.php

<?php

/**
 * Backend for serilized_data
 */
namespace Vendor\Module\Model\Product\Attribute\Backend;

class Customserializeddata
extends \Magento\Eav\Model\Entity\Attribute\Backend\Serialized  // I know this calss does not exist in magento 2.2.5 now but I have added it customly for my requirement which extends below (AbstractBackend) class
// extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend

{

    /**
     * Serialize or remove before saving
     *
     * @param \Magento\Catalog\Model\Product $product
     * @return void
     */
    public function beforeSave($product)
    {
        if ($product->hasIsSerializedData()) {
            if ($product->getIsSerializedData()) {
                parent::beforeSave($product);
            } else {
                $product->unsSerilizedData();
            }
        }
    }


    protected function _unserialize(\Magento\Framework\DataObject $product)
    {
        if ($product->hasIsSerializedData()) {
            if ($product->getIsSerializedData()) {
                parent::_unserialize($product);
            } else {
                $product->unsSerilizedData();
            }
        }
    }

}

Magento\Eav\Model\Entity\Attribute\Backend\Serialized.php

<?php

namespace Magento\Eav\Model\Entity\Attribute\Backend;
/**
 * "Serialized" attribute backend
 */
class Serialized extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
{
    /**
     * Serialize before saving
     *
     * @param \Magento\Framework\DataObject $object
     * @return $this
     */
    public function beforeSave($object)
    {
        // parent::beforeSave() is not called intentionally
        $attrCode = $this->getAttribute()->getAttributeCode();
        if ($object->hasData($attrCode)) {
            $object->setData($attrCode, serialize($object->getData($attrCode)));
        }
        return $this;
    }
    /**
     * Unserialize after saving
     *
     * @param \Magento\Framework\DataObject $object
     * @return $this
     */
    public function afterSave($object)
    {
        parent::afterSave($object);
        $this->_unserialize($object);
        return $this;
    }
    /**
     * Unserialize after loading
     *
     * @param \Magento\Framework\DataObject $object
     * @return $this
     */
    public function afterLoad($object)
    {
        parent::afterLoad($object);
        $this->_unserialize($object);
        return $this;
    }
    /**
     * Try to unserialize the attribute value
     *
     * @param \Magento\Framework\DataObject $object
     * @return $this
     */
    protected function _unserialize(\Magento\Framework\DataObject $object)
    {
        $attrCode = $this->getAttribute()->getAttributeCode();
        if ($object->getData($attrCode)) {
            try {
                $unserialized = unserialize($object->getData($attrCode));
                $object->setData($attrCode, $unserialized);
            } catch (\Exception $e) {
                $object->unsetData($attrCode);
            }
        }
        return $this;
    }
}

Currently serilized_data is displayed in tab in edit product page as text input and I can save and edit the values. But the fields created with the 'product_form.xml' can not be saved data into 'serilized_data' attribute.

1 Answer 1

0

I just missed to add the original attribute-Id serialize_data before field name in which I need to save it.

Which'll turn the product[field_1] post data to product[serialize_data][field_1]

See my updated file

app\code\Vendor\Module\view\adminhtml\ui_component\product_form.xml

<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
-->
<form xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd">
   <fieldset name="serialize-data">
        <fieldset name="fieldset_test" sortOrder="10">
            <argument name="data" xsi:type="array">
                <item name="config" xsi:type="array">
                    <item name="scopeLabel" xsi:type="string">[GLOBAL]</item>
                </item>
            </argument>
            <settings>
                <label translate="true"/>
            </settings>
            <container>
                <field name="field_1" sortOrder="10" formElement="select">
                    <argument name="data" xsi:type="array">
                        <item name="config" xsi:type="array">
                            <item name="rawOptions" xsi:type="boolean">true</item>
                        </item>
                    </argument>
                    <settings>
                        <scopeLabel>[GLOBAL]</scopeLabel>
                        <label translate="true">Product Can Has Serialize Data</label>
                        <dataScope>serialize_data.field_1</dataScope>
                        <imports>
                            <link name="visible">${$.provider}:data.product.is_serialized_data</link>
                        </imports>
                    </settings>
                    <formElements>
                        <select>
                            <settings>
                                <options class="Magento\Config\Model\Config\Source\Yesno"/>
                            </settings>
                        </select>
                    </formElements>
                </field>
                <field name="field_2" sortOrder="20" formElement="input">
                    <settings>
                        <scopeLabel>[GLOBAL]</scopeLabel>
                        <label translate="true">Test Data</label>
                        <notice translate="true">Text Input going save as serialize-data/json data in serilized_data product's attribute attribute.</notice>
                        <dataScope>serialize_data.field_2</dataScope>
                        <imports>
                            <link name="visible">${$.provider}:data.product.is_serialized_data</link>
                        </imports>
                    </settings>
                </field>
            </container>
        </fieldset>
    </fieldset>
</form>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.