3

I'm trying to add an extension attribute to a product attribute (\Magento\Catalog\Model\ResourceModel\Eav\Attribute). I've tried the documentations' examples and various articles on Magento Stack Exchange, but I can't get it to work.

Currently I have the following:

etc/extension_attributes.xml:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
    <extension_attributes for="\Magento\Catalog\Api\Data\ProductAttributeInterface">
        <attribute code="additions" type="array"/>
    </extension_attributes>
</config>

Now if I understand it correctly, this should already return something other than NULL when I call $attribute->getExtensionAttributes() right? Because currently it doesn't, and I'm clueless to why.

I'm using an event to load additional data and put it into the extension attribute but with no success.

I've also tried applying it directly to the attribute class, rather than the interface, but with no success.

Does anyone has more experience with extension attributes?

2
  • You want to get product additions attribute value right? Jan 27, 2017 at 9:22
  • No. I want to iterate over alle product attributes and add extra information to it. So it's not get the attribute of a product, but rather get the additions of an attribute of a product. Additions have no relation to the product, but to the attribute. Is this clear? Jan 27, 2017 at 10:57

3 Answers 3

6

If what you mean is adding extension attribute named Addition (model) for Product model, this may help you.

Create or append extension_attributes.xml configuration.

app/code/ProjectName/ModuleName/etc/extension_attributes.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">

    ....

    <extension_attributes for="Magento\Catalog\Api\Data\ProductInterface">
        <attribute code="additions" type="ProjectName\ModuleName\Model\Addition[]"></attribute>
    </extension_attributes>
</config>

Create Addition model.

app/code/ProjectName/ModuleName/Model/Addition.php

<?php

namespace ProjectName\ModuleName\Model;

use Magento\Framework\Model\AbstractModel;

class Addition extends AbstractModel
{
    ....
}

Create Addition resource.

app/code/ProjectName/ModuleName/Model/ResourceModel/Addition.php

<?php

namespace ProjectName\ModuleName\Model\ResourceModel;

use Magento\Framework\Model\ResourceModel\Db\AbstractDb;

class Addition extends AbstractDb
{
    ....
}

Create Addition collection.

app/code/ProjectName/ModuleName/Model/Addition/Collection.php

<?php

namespace ProjectName\ModuleName\Model\Addition;

use Magento\Catalog\Model\Product as ProductModel;

class Collection extends AbstractCollection
{
    ....

    public function addProductFilter($product)
    {
        if ($product instanceof ProductModel) {
            $product = $product->getId();
        }

        if (is_array($product)) {
            $this->addFieldToFilter('product_id', array('IN' => $product));
        } else {
            $this->addFieldToFilter('product_id', $product);
        }

        return $this;
    }
}

Create Product model plugin configuration.

app/code/ProjectName/ModuleName/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">

    ....

    <type name="Magento\Catalog\Model\Product">
        <plugin name="projectname_modulename_catalog_product_plugin" type="ProjectName\ModuleName\Plugin\Catalog\Model\Product"/>
    </type>
</config>

Create Product model plugin class.

app/code/ProjectName/ModuleName/Plugin/Catalog/Model/Product.php

<?php

namespace ProjectName\ModuleName\Plugin\Catalog\Model;

use Magento\Catalog\Model\Product as ProductModel;
use Magento\Catalog\Api\Data\ProductExtensionFactory;
use ProjectName\ModuleName\Model\Addition\CollectionFactory as AdditionCollectionFactory;

class Product
{
    protected $productExtensionFactory;
    protected $additionCollectionFactory;

    public function __construct(
        ProductExtensionFactory $productExtensionFactory,
        AdditionCollectionFactory $additionCollectionFactory
    ) {
        $this->productExtensionFactory   = $productExtensionFactory;
        $this->additionCollectionFactory = $additionCollectionFactory;
    }

    public function afterLoad(ProductModel $product)
    {
        $productExtension = $product->getExtensionAttributes();
        if (null === $productExtension) {
            $productExtension = $this->productExtensionFactory->create();
        }

        $additionCollection = $this
            ->additionCollectionFactory
            ->create()
            ->addProductFilter($product->getId())
        ;

        $productExtension->setAdditions($additionCollection->getItems());
        $product->setExtensionAttributes($productExtension);

        return $product;
    }
}
2
  • hi @rendy ko prastiyo is this concept for product Api? Dec 28, 2017 at 9:58
  • @NagarajuKasa yes of course, product extension attributes are applicable to product API. Dec 29, 2017 at 9:48
3

Attribute type cannot be set to "array", it must be one of simple types declared in \Magento\Framework\Reflection\TypeProcessor, or data interface. It can also be an array, but item type should be specific, e.g. integer[].

After fixing that make sure to clear var/generation to initiate extension interface regeneration, \Magento\Eav\Api\Data\AttributeExtensionInterface should have getAdditions() and setAdditions() methods generated.

Then you should be able to get/set data to this field from observer or plugin.

1
  • This is a nice simple solution, but in my testing with it, only serialized data will be returned by the API. ``` "customer_tags": [ "{\"tag_id\":\"7333\",\"tag_name\":\"Great customer\"}" ], ```
    – PromInc
    Apr 1, 2022 at 16:15
0

In file app/code/Namespance/Module/etc/extension_attributes.xml add the attribute. The type is set to a core Magento class.

<attribute code="new_attribute_name" type="Magento\Framework\Api\AttributeValue[]" />

Then elsewhere in the code where the extension data is set, assign an array to this extension attribute.

$extensionAttributes = $order->getExtensionAttributes()
    ? $order->getExtensionAttributes()
    : $this->orderExtensionFactory->create();

$newAttributeNameData = [];
foreach( $sourceData AS $dataItem ) {
  $newAttributeNameData [] = [ 'key_1' => $dataItem ['key_1'], 'key_2' => $dataItem ['key_2'] ];
}

$extensionAttributes->setNewAttributeName( $newAttributeNameData );

$object->setExtensionAttributes( $extensionAttributes );

Your Answer

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

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