Skip to content

Fastest way to get attribute value of custom product attribute by attribute_code and sku

Hello fellow Magento developers,

What is the most efficient way of getting an attribute value of a custom eav product attribute, by only using its attribute_code and the products sku?

=> The question mainly targets the most efficient way, but answers with maintainability in mind (i.e. readable, more update secure abstractions etc.) would be great!

Background:

The objective is to hook into the method of a PIM connector module via a plugin (interceptor), that is responsible for pushing several hundreds of products into the Magento 2 database. The plugins function itself is not relevant, however it has to run checks on every product by getting the products attribute value (product: by given sku; attribute: by given attribute_code).

The PIM connector module works like this:

  1. handling data for several products in batch (~100 products per batch)
  2. pushing the data from 1.) product entities as well as their attributes into the database (more or less directly: “simplified explanation”).

The plugin hooks into the step 1.) and iterates over all 100 products of the batch and needs for every product as product sku i.e. ‘STRING_SKU_HERE’ the attribute value with attribute_code ‘MY_ATTRIBUTE_CODE’.

Because the procedure may apply for thousands of products, it is important that the plugin and custom logic does not significally slow down the process.

Previous attempts:

Although it is not representative, we have counted the time for fetching the needed data by using several different options.

  1. try: using ProductCollection and raw SQL
/** @var MagentoCatalogModelResourceModelProductCollection $collection */
$collection = $this->productCollectionFactory->create();

$collection
    ->getConnection()
    ->query(
        "SELECT e.sku, e.entity_id, e.attribute_set_id, sub.*
            FROM
                `catalog_product_entity` e
            JOIN
                (
                    SELECT row_id, value_id, value
                    FROM `catalog_product_entity_varchar` enityvarchar
                    WHERE enityvarchar.attribute_id = (
                        SELECT attribute_id
                        FROM `eav_attribute`
                        WHERE `attribute_code` = 'MY_ATTRIBUTE_CODE'
                    )
                ) sub
                ON (e.entity_id = sub.row_id)
                WHERE sub.value IS NOT NULL AND e.sku = 'STRING_SKU_HERE'"
        )
        ->fetch();

=> Time consumed: float(0.00023388862609863)

  • (+ +) time
  • (- -) maintainability
  1. try : pure ProductCollection
/** @var MagentoCatalogModelResourceModelProductCollection $collection */
$collection = $this->productCollectionFactory->create();

$collection
    ->addAttributeToSelect('STRING_SKU_HERE')
    ->addAttributeToFilter('sku', ['STRING_SKU_HERE'])
    ->getFirstItem()
    ->getData('MY_ATTRIBUTE_CODE');

=> Time consumed: float(0.0028450489044189)

  • (+) time (~10 times slower than 1.) )
  • (+) maintainability
  • (-) unnecessary product instantiation
  1. try: via ProductResource
/** @var MagentoCatalogModelProduct $product */
$product = $this->productFactory->create();

/** @var MagentoCatalogModelResourceModelProduct $productResource */
$productResource = $product->getResource(); 

$productId = $productResource->getIdBySku('STRING_SKU_HERE');
$productResource->load($product, $productId, ['MY_ATTRIBUTE_CODE']);
$product->getData('MY_ATTRIBUTE_CODE');

=> Time consumed: float(0.0058329105377197)

  • (+) maintainability
  • (-) unnecessary product instantiation
  • (-) time (not very fast, but also not very slow)
  1. try: via ProductRepository
/** @var MagentoCatalogModelProductRepository $productRepository */
$productRepository = $this->productRepository;

$product = $productRepository->get('STRING_SKU_HERE');
$product->getData('MY_ATTRIBUTE_CODE');

=> Time consumed: float(0.44260311126709)

  • (++) maintainability
  • (-) unnecessary product instantiation
  • (–) time (~ very very slow compared to 1.), 2.) 3.) )

Thanks in advance!

EDIT:
Current test 2022-07-11 including variants of comments below (results vary of course (!) , they are not representative but indicators of the time consumption on my machine):

  • Variant 1 (original question): float(0.00022697448730469)
  • Variant 2 (original question): float(0.0026819705963135)
  • Variant 3 (original question): float(0.040131092071533)
  • Variant 4 (original question): float(0.027424097061157)
  • Variant 5 (1. variant by @victor-tihonchuk): float(0.00026488304138184)
  • Variant 6 (2. variant by @victor-tihonchuk): float(0.0004880428314209)

I’m curious about more opportunities. 🙂