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.