The question:
I added custom field Image and Qty in Product Customizable Options.
I add those filed to Product Option Value in Product Rest API. So how can it possible.
Method: GET
API Request URL:
http://localhost/magentosample231/rest/V1/products/24-MB01
Reposne:
{
"id": 1,
"sku": "24-MB01",
"name": "Joust Duffle Bag",
"attribute_set_id": 15,
"price": 34,
"status": 1,
"visibility": 4,
"type_id": "simple",
"created_at": "2019-08-30 07:14:51",
"updated_at": "2019-10-16 11:56:24",
"extension_attributes": {
"website_ids": [
1
],
"category_links": [
{
"position": 0,
"category_id": "3"
},
{
"position": 0,
"category_id": "4"
}
],
"stock_item": {
"item_id": 1,
"product_id": 1,
"stock_id": 1,
"qty": 100,
"is_in_stock": true,
"is_qty_decimal": false,
"show_default_notification_message": false,
"use_config_min_qty": true,
"min_qty": 0,
"use_config_min_sale_qty": 1,
"min_sale_qty": 1,
"use_config_max_sale_qty": true,
"max_sale_qty": 10000,
"use_config_backorders": true,
"backorders": 0,
"use_config_notify_stock_qty": true,
"notify_stock_qty": 1,
"use_config_qty_increments": true,
"qty_increments": 0,
"use_config_enable_qty_inc": true,
"enable_qty_increments": false,
"use_config_manage_stock": true,
"manage_stock": true,
"low_stock_date": null,
"is_decimal_divided": false,
"stock_status_changed_auto": 0
}
},
"product_links": [
{
"sku": "24-MB01",
"link_type": "crosssell",
"linked_product_sku": "24-WG086",
"linked_product_type": "simple",
"position": 1
},
{
"sku": "24-MB01",
"link_type": "crosssell",
"linked_product_sku": "24-WG083-blue",
"linked_product_type": "simple",
"position": 2
},
{
"sku": "24-MB01",
"link_type": "crosssell",
"linked_product_sku": "24-UG01",
"linked_product_type": "simple",
"position": 3
},
{
"sku": "24-MB01",
"link_type": "crosssell",
"linked_product_sku": "24-WG085_Group",
"linked_product_type": "grouped",
"position": 4
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-MB02",
"linked_product_type": "simple",
"position": 1
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-MB03",
"linked_product_type": "simple",
"position": 2
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-MB05",
"linked_product_type": "simple",
"position": 3
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-MB06",
"linked_product_type": "simple",
"position": 4
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-UB02",
"linked_product_type": "simple",
"position": 5
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-WB03",
"linked_product_type": "simple",
"position": 6
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-WB04",
"linked_product_type": "simple",
"position": 7
},
{
"sku": "24-MB01",
"link_type": "upsell",
"linked_product_sku": "24-WB07",
"linked_product_type": "simple",
"position": 8
}
],
"options": [
{
"product_sku": "24-MB01",
"option_id": 1,
"title": "Test",
"type": "drop_down",
"sort_order": 1,
"is_require": true,
"max_characters": 0,
"image_size_x": 0,
"image_size_y": 0,
"values": [
{
"title": "Test1",
"sort_order": 1,
"price": 10,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 1
},
{
"title": "Test2",
"sort_order": 2,
"price": 12,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 2
}
]
}
],
"media_gallery_entries": [
{
"id": 1,
"media_type": "image",
"label": "Image",
"position": 1,
"disabled": false,
"types": [
"image",
"small_image",
"thumbnail"
],
"file": "/m/b/mb01-blue-0.jpg"
}
],
"tier_prices": [],
"custom_attributes": [
{
"attribute_code": "activity",
"value": []
},
{
"attribute_code": "style_bags",
"value": []
},
{
"attribute_code": "material",
"value": []
},
{
"attribute_code": "color",
"value": [
{
"Title": "Color",
"label": "Black",
"code": "49",
"Visible on Storefront": "1"
}
]
},
{
"attribute_code": "strap_bags",
"value": []
},
{
"attribute_code": "features_bags",
"value": []
},
{
"attribute_code": "image",
"value": "/m/b/mb01-blue-0.jpg"
},
{
"attribute_code": "small_image",
"value": "/m/b/mb01-blue-0.jpg"
},
{
"attribute_code": "thumbnail",
"value": "/m/b/mb01-blue-0.jpg"
},
{
"attribute_code": "options_container",
"value": "container1"
},
{
"attribute_code": "msrp_display_actual_price_type",
"value": "0"
},
{
"attribute_code": "url_key",
"value": "joust-duffle-bag"
},
{
"attribute_code": "gift_message_available",
"value": "0"
},
{
"attribute_code": "required_options",
"value": "1"
},
{
"attribute_code": "has_options",
"value": "1"
},
{
"attribute_code": "image_label",
"value": "Image"
},
{
"attribute_code": "small_image_label",
"value": "Image"
},
{
"attribute_code": "thumbnail_label",
"value": "Image"
},
{
"attribute_code": "tax_class_id",
"value": "0"
},
{
"attribute_code": "category_ids",
"value": [
"3",
"4"
]
},
{
"attribute_code": "description",
"value": "<p>The sporty Joust Duffle Bag can't be beat - not in the gym, not on the luggage carousel, not anywhere. Big enough to haul a basketball or soccer ball and some sneakers with plenty of room to spare, it's ideal for athletes with places to go.<p>rn<ul>rn<li>Dual top handles.</li>rn<li>Adjustable shoulder strap.</li>rn<li>Full-length zipper.</li>rn<li>L 29" x W 13" x H 11".</li>rn</ul>"
},
{
"attribute_code": "eco_collection",
"value": "0"
},
{
"attribute_code": "performance_fabric",
"value": "0"
},
{
"attribute_code": "erin_recommends",
"value": "0"
},
{
"attribute_code": "new",
"value": "0"
},
{
"attribute_code": "sale",
"value": "0"
}
]
}
See the reposne there is a “options”
"options": [
{
"product_sku": "24-MB01",
"option_id": 1,
"title": "Test",
"type": "drop_down",
"sort_order": 1,
"is_require": true,
"max_characters": 0,
"image_size_x": 0,
"image_size_y": 0,
"values": [
{
"title": "Test1",
"sort_order": 1,
"price": 10,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 1
},
{
"title": "Test2",
"sort_order": 2,
"price": 12,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 2
}
]
}
],
I have to add my custom added options field Image
and Qty
in to the Options
Value
like same as below.
"options": [
{
"product_sku": "24-MB01",
"option_id": 1,
"title": "Test",
"type": "drop_down",
"sort_order": 1,
"is_require": true,
"max_characters": 0,
"image_size_x": 0,
"image_size_y": 0,
"values": [
{
"title": "Test1",
"sort_order": 1,
"price": 10,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 1,
"image": "test.jpg",
"qty": 2
},
{
"title": "Test2",
"sort_order": 2,
"price": 12,
"price_type": "fixed",
"sku": "24-MB01",
"option_type_id": 2,
"image": "info.jpg",
"qty": 1
}
]
}
],
Any help would be appreciated. Thanks!
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
I took a quick look and I think you have to work around this class MagentoCatalogModelProductOption
, there is a method called addValue()
which is a public function. You might do a plugin.
Hope it helps.
Method 2
Finally I have added product custom option value to product Rest API using Plugin MagentoCatalogModelProductOptionReadHandler
class.
Follow below file path to create custom module and add the product custom option value to the Product Rest API.
File path: magento/app/code/Vendor/ProductoptionsApi/registration.php
<?php
MagentoFrameworkComponentComponentRegistrar::register(
MagentoFrameworkComponentComponentRegistrar::MODULE,
'Vendor_ProductoptionsApi',
__DIR__
);
File path: magento/app/code/Vendor/ProductoptionsApi/etc/module.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Vendor_ProductoptionsApi" setup_version="1.0.0">
</module>
</config>
File path:
magento/app/code/Vendor/ProductoptionsApi/etc/webapi_rest/di.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="MagentoCatalogModelProductOptionReadHandler">
<plugin name="updateProductCustomOptionsValue" type="VendorProductoptionsApiPluginProductCustomOptionsValue"/>
</type>
</config>
File path:
magento/app/code/Vendor/ProductoptionsApi/Plugin/ProductCustomOptionsValue.php
<?php
namespace VendorProductoptionsApiPlugin;
use MagentoCatalogApiProductCustomOptionRepositoryInterface;
use MagentoCatalogModelProductOptionFactory;
use MagentoFrameworkEntityManagerMetadataPool;
use MagentoFrameworkEntityManagerOperationExtensionInterface;
class ProductCustomOptionsValue
{
/**
* @var ProductCustomOptionRepositoryInterface
*/
protected $optionRepository;
/**
* @param ProductCustomOptionRepositoryInterface $optionRepository
*/
public function __construct(
ProductCustomOptionRepositoryInterface $optionRepository,
VendorProductoptionsApiHelperOptionsProvider $optionProvider,
MagentoCatalogBlockProductViewOptions $productOptions
) {
$this->optionRepository = $optionRepository;
$this->optionProvider = $optionProvider;
$this->productOptions = $productOptions;
}
public function afterExecute(MagentoCatalogModelProductOptionReadHandler $subject, $result, $entity, $arguments = [])
{
$options = $dataOption = [];
$productSku = $entity->getSku();
$options = $this->productOptions->decorateArray($this->optionRepository->getProductOptions($entity));
$dataOption = $this->optionProvider->getExtendedOptionsConfig($options, $productSku);
if($dataOption != '' && $dataOption != null && $dataOption != '[]'){
$entity->setOptions($dataOption);
}else{
$options = [];
/** @var $entity MagentoCatalogApiDataProductInterface */
foreach ($this->optionRepository->getProductOptions($entity) as $option) {
$option->setProduct($entity);
$options[] = $option;
}
$entity->setOptions($options);
}
return $entity;
}
}
File path:
magento/app/code/Vendor/ProductoptionsApi/Helper/OptionsProvider.php
<?php
declare(strict_types=1);
namespace VendorProductoptionsApiHelper;
use MageWorxOptionBaseModelProductOptionAttributes as OptionAttributes;
use MageWorxOptionBaseModelProductOptionValueAttributes as OptionValueAttributes;
use MagentoFrameworkPricingHelperData;
use MagentoCatalogHelperImage as ImageHelper;
use MagentoFrameworkAppFilesystemDirectoryList;
use MagentoFrameworkExceptionFileSystemException;
use MagentoFrameworkJsonEncoderInterface;
use MagentoFrameworkViewElementAbstractBlock;
use MageWorxOptionFeaturesModelImage;
use MageWorxOptionFeaturesModelProductOptionValueMediaConfig;
/**
* class OptionsProvider
*/
class OptionsProvider
{
/**
* @var array
*/
protected $productOptions;
/**
* Constructor
*
* @param array $components
*/
public function __construct(
MagentoCatalogBlockProductViewOptions $productOptions,
OptionAttributes $optionAttributes,
OptionValueAttributes $optionValueAttributes,
MagentoFrameworkJsonEncoderInterface $jsonEncoder,
Data $priceHelper,
MagentoFrameworkJsonHelperData $jsonHelper,
Config $mediaConfig,
ImageHelper $imageHelper,
MagentoFrameworkFilesystem $filesystem
) {
$this->productOptions = $productOptions;
$this->optionAttributes = $optionAttributes;
$this->optionValueAttributes = $optionValueAttributes;
$this->_jsonEncoder = $jsonEncoder;
$this->priceHelper = $priceHelper;
$this->jsonHelper = $jsonHelper;
$this->mediaConfig = $mediaConfig;
$this->imageHelper = $imageHelper;
$this->_filesystem = $filesystem;
}
public function getExtendedOptionsConfig($options, $productSku = '')
{
$config = $result = [];
$optionAttributes = $this->optionAttributes->getData();
$optionValueAttributes = $this->optionValueAttributes->getData();
/** @var MagentoCatalogModelProductOption $option */
if (empty($options)) {
return $this->_jsonEncoder->encode($config);
}
foreach ($options as $option) {
$config[$option->getId()]['title']= $option->getTitle();
$config[$option->getId()]['type']= $option->getType();
$config[$option->getId()]['sort_order']= $option->getSortOrder();
$config[$option->getId()]['option_id']= $option->getId();
$config[$option->getId()]['product_sku']= $productSku;
$config[$option->getId()]['is_require']= $option->getIsRequire();
$config[$option->getId()]['max_characters']= $option->getMaxCharacters();
$config[$option->getId()]['image_size_x']= $option->getImageSizeX();
$config[$option->getId()]['image_size_y']= $option->getImageSizeY();
foreach ($optionAttributes as $optionAttribute) {
$preparedData = $optionAttribute->prepareDataForFrontend($option);
if (empty($preparedData) || !is_array($preparedData)) {
continue;
}
foreach ($preparedData as $preparedDataKey => $preparedDataValue) {
$config[$option->getId()][$preparedDataKey] = $preparedDataValue;
}
}
/** @var MagentoCatalogModelProductOptionValue $value */
if (empty($option->getValues())) {
continue;
}
$i = 0;
foreach ($option->getValues() as $value) {
foreach ($optionValueAttributes as $optionValueAttribute) {
$preparedData = $optionValueAttribute->prepareDataForFrontend($value);
if (empty($preparedData) || !is_array($preparedData)) {
continue;
}
}
$config[$option->getId()]['values'][$i]['sort_order'] = $value->getSortOrder();
$config[$option->getId()]['values'][$i]['price_type'] = $value->getPriceType();
$config[$option->getId()]['values'][$i]['title'] = $value->getTitle();
$config[$option->getId()]['values'][$i]['price'] = $value->getDefaultPrice();
$config[$option->getId()]['values'][$i]['dependency'] = $value->getDependency();
$config[$option->getId()]['values'][$i]['dependency_type'] = $value->getDependencyType();
$config[$option->getId()]['values'][$i]['image'] = $value->getImagesData();
$config[$option->getId()]['values'][$i]['option_type_id'] = $value->getId();
$config[$option->getId()]['values'][$i]['price_type'] = $value->getPriceType();
$config[$option->getId()]['values'][$i]['color_code'] = $value->getTitle();
$i++;
}
}
return $config;
}
public function getDependency($dependency){
$dependencyArray=[];
$dependency = json_decode($dependency);
foreach($dependency as $key=>$value)
{
$dependencyArray['key'][$key]=$value[0];
$dependencyArray['value'][$key]=$value[1];
}
return $dependencyArray;
}
}
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0