Magento 2 – Custom Values for Custom Attribute with $product->getData()

magento2product-attribute

I have attribute that values are dynamically mapped from custom tables. So attribute don't have values by it self. I'd like to get mapped values every time getValue() is called. But i don't want affect core magento files with additional "if's".

For admin panel i created backend_model for this attribute and method afterLoad() with my custom logic for this attribute. At admin panel it works fine.

But i have problem with Product model and $product->getData(). In this call of course it returns data directly from DB. Without backend model logic.

Is there any place that I can add logic for fetching values for this attribute, that it will be visible at $product->getData()? Maybe some model for this attribute? But it's just idea but don't know why.

For some reasons perfect solution is to not use any plugins, preferences for core magento files. That's why i think about some models mayby.

Can anyone help? Any tips?


EDIT

I'm trying to use it in magento import-export module.

Best Answer

You can create 2 plugins for after load method for collection and product.

Plugin declaration

app/code/Acme/StackExchange/etc/di.xml

<?xml version="1.0" encoding="UTF-8"?>
<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="Acme_StackExchange_Plugin_Catalog_Model_ProductPlugin"
                type="Acme\StackExchange\Plugin\Catalog\Model\ProductPlugin" sortOrder="10"/>
    </type>
    <type name="Magento\Catalog\Model\ResourceModel\Product\Collection">
        <plugin name="Acme_StackExchange_Plugin_Catalog_Model_ResourceModel_Product_CollectionPlugin"
                type="Acme\StackExchange\Plugin\Catalog\Model\ResourceModel\Product\CollectionPlugin" sortOrder="10"/>
    </type>
</config>

Product Model Plugin

app/code/Acme/StackExchange/Plugin/Catalog/Model/ProductPlugin.php

<?php
declare(strict_types=1);

namespace Acme\StackExchange\Plugin\Catalog\Model;

use Magento\Catalog\Model\Product;

class ProductPlugin
{
    public function afterLoad(Product $product)
    {
        // load your custom data and assign to $product instance

        return $product;
    }
}

Product Collection Plugin

app/code/Acme/StackExchange/Plugin/Catalog/Model/ResourceModel/Product/CollectionPlugin.php

<?php
declare(strict_types=1);

namespace Acme\StackExchange\Plugin\Catalog\Model\ResourceModel\Product;

use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\ResourceModel\Product\Collection;

class CollectionPlugin
{
    protected bool $isLoaded = false;

    public function beforeLoad(Collection $subject, $printQuery = false, $logQuery = false): array
    {
        $this->isLoaded = $subject->isLoaded();

        return [$printQuery, $logQuery];
    }

    public function afterLoad(Collection $subject, Collection $result): Collection
    {
        if (!$this->isLoaded) {
            $this->isLoaded = true;

            // collect loaded product ids
            $productIds = [];
            /** @var Product $product */
            foreach ($subject->getItems() as $product) {
                $productIds[] = $product->getId();
            }

            // load your data for $productIds

            foreach ($subject->getItems() as $product) {
                // check is data loaded for $product
                // assign loaded data to $product instance
            }
        }

        return $result;
    }
}