Magento 2 Attribute Error – Fix Missing Setter in AttributeOptionInterface

apiattributesinterfacemagento2

I am trying to override Magento\Eav\Api\Data\AttributeOptionInterface in my custom module. I want to add one new option to existing interface.

The idea behind is, As of now we can only pass defined options data in attribute options REST API

See below API request format for more clarity.

Api

Url = http://test.com/index.php/rest/V1/products/attributes/manufacturer/options/
Api Methodd - Post
Api body - {
  "option": {
    "label": "test",
    "is_default": "true",
  }
}

As of now its passing 3 parameters as value, I want to add my custom 4th parameters Ex – Slider.

So parameters should be

{
  "option": {
    "label": "test",
    "is_default": "true",
    "slider":"test1"
  }
}

I have tried to override interface and its method but its giving property setter not defined

Error Message

"message": "Property \"Slider\" does not have corresponding setter in class \"Magento\\Eav\\Api\\Data\\AttributeOptionInterface\"."

So here my question is how can I override API interface and pass my custom or add my option in existing parameters.

Thanks.

Best Answer

To resolve this issue, We require to override mainly two interfaces and model. After overriding interfaces and model, Overrided interfaces requires binding with model using di.xml to initiate objects while API call.

Check the below code to add new fields to AttributeOptionInterface.

[Package_Name][Module_Name]\etc\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">  
    <preference for="Magento\Eav\Model\Entity\Attribute\Option" type="[Package_Name]\[Module_Name]\Model\Eav\Entity\Attribute\Option" />  
    <preference for="[Package_Name]\[Module_Name]\Api\Eav\Data\AttributeOptionInterface" type="[Package_Name]\[Module_Name]\Model\Eav\Entity\Attribute\Option" />
    <preference for="[Package_Name]\[Module_Name]\Api\Catalog\ProductAttributeOptionManagementInterface" type="Magento\Catalog\Model\Product\Attribute\OptionManagement" />
</config>

[Package_Name][Module_Name]\Api\Eav\Data\AttributeOptionInterface.php

<?php 

namespace [Package_Name]\[Module_Name]\Api\Eav\Data;

interface AttributeOptionInterface extends \Magento\Eav\Api\Data\AttributeOptionInterface
{
    /**
     * Get slider
     *
     * @return string
     */
    public function getSlider();

    /**
     * Set slider
     *
     * @param string $slider
     * @return $this
     */
    public function setSlider($slider);
}

[Package_Name][Module_Name]\Model\Eav\Entity\Attribute\Option.php

<?php 

namespace [Package_Name]\[Module_Name]\Model\Eav\Entity\Attribute;

class Option extends \Magento\Eav\Model\Entity\Attribute\Option implements \Ktpl\SliderEavOptions\Api\Eav\Data\AttributeOptionInterface
{
    /**
     * {@inheritdoc}
     */
    public function getSlider()
    {
        return $this->getData('slider');
    }

    /**
     * Set slider value
     *
     * @param string $slider
     * @return $this
     */
    public function setSlider($slider)
    {
        return $this->setData('slider', $slider);
    }
}

After overriding interface to add 'slider' field and overring option.php, it is required to change the parameter type of API call for attribute options in webapi.xml for Magento_Catalog module.

[Package_Name][Module_Name]\etc\webapi.xml

<?xml version="1.0"?>

<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
    <route url="/V1/products/attributes/:attributeCode/options" method="GET">
        <service class="[Package_Name]\[Module_Name]\Api\Catalog\ProductAttributeOptionManagementInterface" method="getItems"/>
        <resources>
            <resource ref="Magento_Catalog::attributes_attributes" />
        </resources>
    </route>    
    <route url="/V1/products/attributes/:attributeCode/options" method="POST">
        <service class="[Package_Name]\[Module_Name]\Api\Catalog\ProductAttributeOptionManagementInterface" method="add" />
        <resources>
            <resource ref="Magento_Catalog::attributes_attributes" />
        </resources>
    </route>    
    <route url="/V1/products/attributes/:attributeCode/options/:optionId" method="DELETE">
        <service class="[Package_Name]\[Module_Name]\Api\Catalog\ProductAttributeOptionManagementInterface" method="delete" />
        <resources>
            <resource ref="Magento_Catalog::attributes_attributes" />
        </resources>
    </route>        
</routes>

And Finally,

[Package_Name][Module_Name]\Api\Catalog\ProductAttributeOptionManagementInterface.php

<?php

namespace [Package_Name]\[Module_Name]\Api\Catalog;

/**
 * @api
 */
interface ProductAttributeOptionManagementInterface
{
    /**
     * Retrieve list of attribute options
     *
     * @param string $attributeCode
     * @throws \Magento\Framework\Exception\StateException
     * @throws \Magento\Framework\Exception\InputException
     * @return \Ktpl\SliderEavOptions\Api\Eav\Data\AttributeOptionInterface[]
     */
    public function getItems($attributeCode);

    /**
     * Add option to attribute
     *
     * @param string $attributeCode
     * @param \Ktpl\SliderEavOptions\Api\Eav\Data\AttributeOptionInterface $option
     * @throws \Magento\Framework\Exception\StateException
     * @throws \Magento\Framework\Exception\InputException
     * @return bool
     */
    public function add($attributeCode, $option);

    /**
     * Delete option from attribute
     *
     * @param string $attributeCode
     * @param string $optionId
     * @throws \Magento\Framework\Exception\StateException
     * @throws \Magento\Framework\Exception\NoSuchEntityException
     * @throws \Magento\Framework\Exception\InputException
     * @return bool
     */
    public function delete($attributeCode, $optionId);
}
Related Topic