Question

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?

Was it helpful?

Solution

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;
    }
}

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top