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:
- handling data for several products in batch (~100 products per batch)
- 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.
- 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
- 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
- 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)
- 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. 🙂