From 2c3a2c9ce5ab2646ed3b99ccf092ebd5789d2efa Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Sat, 4 Oct 2025 14:37:52 +0700 Subject: [PATCH 1/7] #40216-Replacing nested foreach with array_replace to reduce time complexity --- .../Entity/Collection/AbstractCollection.php | 49 +++++++++++-------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index d8762eb604f00..c8c971b60fcca 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1233,9 +1233,27 @@ public function _loadAttributes($printQuery = false, $logQuery = false) throw $e; } + $attributeCode = $data = []; + $entityIdField = $entity->getEntityIdField(); + foreach ($values as $value) { - $this->_setItemAttributeValue($value); + $entityId = $value[$entityIdField]; + $attributeId = $value['attribute_id']; + if(!isset($attributeCode[$attributeId])) { + $attributeCode[$attributeId] = array_search($attributeId, $this->_selectAttributes); + if (!$attributeCode[$attributeId]) { + $attribute = $this->_eavConfig->getAttribute( + $this->getEntity()->getType(), + $attributeId + ); + $attributeCode[$attributeId] = $attribute->getAttributeCode(); + } + $data[$entityId][$attributeCode[$attributeId]] = $value['value']; + } } + + if($data) + $this->_setItemAttributeValue($data); } } @@ -1303,7 +1321,7 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) /** * Initialize entity object property value * - * Parameter $valueInfo is _getLoadAttributesSelect fetch result row + * Parameter $valueInfo is [product_id => [attribute_code => value]] * * @param array $valueInfo * @return $this @@ -1311,24 +1329,15 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) */ protected function _setItemAttributeValue($valueInfo) { - $entityIdField = $this->getEntity()->getEntityIdField(); - $entityId = $valueInfo[$entityIdField]; - if (!isset($this->_itemsById[$entityId])) { - throw new LocalizedException( - __('A header row is missing for an attribute. Verify the header row and try again.') - ); - } - $attributeCode = array_search($valueInfo['attribute_id'], $this->_selectAttributes); - if (!$attributeCode) { - $attribute = $this->_eavConfig->getAttribute( - $this->getEntity()->getType(), - $valueInfo['attribute_id'] - ); - $attributeCode = $attribute->getAttributeCode(); - } - - foreach ($this->_itemsById[$entityId] as $object) { - $object->setData($attributeCode, $valueInfo['value']); + foreach ($valueInfo as $entityId => $value) { + if (!isset($this->_itemsById[$entityId])) { + throw new LocalizedException( + __('A header row is missing for an attribute. Verify the header row and try again.') + ); + } + $object =$this->_itemsById[$entityId][0]; + $value = array_replace($object->getData(), $value); + $object->setData($value); } return $this; From f3f5bc910dfc21a7117b5300352d06d969fd13d2 Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Sat, 4 Oct 2025 18:02:53 +0700 Subject: [PATCH 2/7] #40216 - array union seems to be better optimised from memory perspective --- .../Model/Entity/Collection/AbstractCollection.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index c8c971b60fcca..f29c9f014fc43 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1,7 +1,7 @@ _selectAttributes); if (!$attributeCode[$attributeId]) { $attribute = $this->_eavConfig->getAttribute( @@ -1252,8 +1252,9 @@ public function _loadAttributes($printQuery = false, $logQuery = false) } } - if($data) + if ($data) { $this->_setItemAttributeValue($data); + } } } @@ -1336,8 +1337,7 @@ protected function _setItemAttributeValue($valueInfo) ); } $object =$this->_itemsById[$entityId][0]; - $value = array_replace($object->getData(), $value); - $object->setData($value); + $object->setData($value+$object->getData()); } return $this; From 85c13c610ffa1f99d4b9575b3d44c8034b4667d9 Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Sat, 4 Oct 2025 19:13:54 +0700 Subject: [PATCH 3/7] #40216 - Moving the setting to outside of if to fix data setting issue --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index f29c9f014fc43..267d9b5b282d3 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1248,8 +1248,8 @@ public function _loadAttributes($printQuery = false, $logQuery = false) ); $attributeCode[$attributeId] = $attribute->getAttributeCode(); } - $data[$entityId][$attributeCode[$attributeId]] = $value['value']; } + $data[$entityId][$attributeCode[$attributeId]] = $value['value']; } if ($data) { From f8d70b602bccbe946f4825c2950f6818e819f90e Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Sun, 5 Oct 2025 10:17:04 +0700 Subject: [PATCH 4/7] #40216 - Moving the attribute value to right side to keep the left array untouched --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 267d9b5b282d3..6a1857cb931a6 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1337,7 +1337,7 @@ protected function _setItemAttributeValue($valueInfo) ); } $object =$this->_itemsById[$entityId][0]; - $object->setData($value+$object->getData()); + $object->setData($object->getData()+$value); } return $this; From 072db63d93c1ea6ccb9f18bf73d3b1c1fb880620 Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Fri, 10 Oct 2025 02:20:33 +0700 Subject: [PATCH 5/7] #40216 - Reproduced WebApiFunctional Test errors & fixed --- .../Eav/Model/Entity/Collection/AbstractCollection.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 6a1857cb931a6..193ed5bb4f276 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1330,14 +1330,17 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) */ protected function _setItemAttributeValue($valueInfo) { + // Run only once foreach ($valueInfo as $entityId => $value) { if (!isset($this->_itemsById[$entityId])) { throw new LocalizedException( __('A header row is missing for an attribute. Verify the header row and try again.') ); } - $object =$this->_itemsById[$entityId][0]; - $object->setData($object->getData()+$value); + // Run only once + foreach ($this->_itemsById[$entityId] as $object) { + $object->setData($object->getData()+$value); + } } return $this; From ab42d6872ec4dc5a61f5423ef44db6e7cde9ffae Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Fri, 10 Oct 2025 02:27:11 +0700 Subject: [PATCH 6/7] #40216 - Removing a confusing comment --- .../Magento/Eav/Model/Entity/Collection/AbstractCollection.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index 193ed5bb4f276..fb18f155cda20 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1330,7 +1330,6 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) */ protected function _setItemAttributeValue($valueInfo) { - // Run only once foreach ($valueInfo as $entityId => $value) { if (!isset($this->_itemsById[$entityId])) { throw new LocalizedException( From 48c2f622eb16276741cf2c4e10b3540d86cda760 Mon Sep 17 00:00:00 2001 From: Senthilkumar Muppidathi Date: Thu, 16 Oct 2025 12:40:10 +0700 Subject: [PATCH 7/7] #40217 - Introduced _setItemAttributeValues function and deprecate _setItemAttributeValue --- .../Entity/Collection/AbstractCollection.php | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php index fb18f155cda20..737a9f07c61f0 100644 --- a/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php +++ b/app/code/Magento/Eav/Model/Entity/Collection/AbstractCollection.php @@ -1253,7 +1253,7 @@ public function _loadAttributes($printQuery = false, $logQuery = false) } if ($data) { - $this->_setItemAttributeValue($data); + $this->_setItemAttributeValues($data); } } } @@ -1322,7 +1322,10 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) /** * Initialize entity object property value * - * Parameter $valueInfo is [product_id => [attribute_code => value]] + * Parameter $valueInfo is _getLoadAttributesSelect fetch result row + * + * @deprecated Batch process of attribute values is introduced to reduce time complexity. + * @see _setItemAttributeValues($entityAttributeMap) uses array union (+) to acheive O(n) complexity. * * @param array $valueInfo * @return $this @@ -1330,18 +1333,53 @@ protected function _addLoadAttributesSelectValues($select, $table, $type) */ protected function _setItemAttributeValue($valueInfo) { - foreach ($valueInfo as $entityId => $value) { + $entityIdField = $this->getEntity()->getEntityIdField(); + $entityId = $valueInfo[$entityIdField]; + if (!isset($this->_itemsById[$entityId])) { + throw new LocalizedException( + __('A header row is missing for an attribute. Verify the header row and try again.') + ); + } + $attributeCode = array_search($valueInfo['attribute_id'], $this->_selectAttributes); + if (!$attributeCode) { + $attribute = $this->_eavConfig->getAttribute( + $this->getEntity()->getType(), + $valueInfo['attribute_id'] + ); + $attributeCode = $attribute->getAttributeCode(); + } + + foreach ($this->_itemsById[$entityId] as $object) { + $object->setData($attributeCode, $valueInfo['value']); + } + + return $this; + } + + /** + * Initialize entity object property value + * + * Parameter $entityAttributeMap is [entity_id => [attribute_code => value, ...]] + * + * @param array $entityAttributeMap + * @return $this + * @throws LocalizedException + */ + protected function _setItemAttributeValues(array $entityAttributeMap) + { + foreach ($entityAttributeMap as $entityId => $attributeValues) { if (!isset($this->_itemsById[$entityId])) { throw new LocalizedException( __('A header row is missing for an attribute. Verify the header row and try again.') ); } - // Run only once + // _itemsById[$entityId] is always an array (typically with one element) + // foreach handles edge cases where multiple objects share the same entity ID foreach ($this->_itemsById[$entityId] as $object) { - $object->setData($object->getData()+$value); + $object->setData($object->getData()+$attributeValues); } - } + } return $this; }