-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Description
Preconditions and environment
- Magento version 2.4.8-p2
Steps to reproduce
Problem is pretty straightforward.
- Set price as global (it's by default)
- Add decimal scoped attribute
example_decimal_attr
- Set decimal attribute value on some products on store scope (not global - store_id > 0)
- Create product collection for scope where created attribute have value (i.e. store_id = 1)
- Add attributes to select:
$collection->setStoreId(1);
$collection->addAttributeToSelect('example_decimal_attr');
$collection->addAttributeToSelect('price');
$collection->load();
Expected result
Loaded products in collection have example_decimal_attr
values.
Actual result
Loaded products in collection does not have example_decimal_attr
values. If we remove price
from collection attributes select, then it works as expected.
This works:
$collection->setStoreId(1);
$collection->addAttributeToSelect('example_decimal_attr');
$collection->load();
Adding $collection->addAttributeToSelect('price');
before loading collection, causes bug, that example_decimal_attr
values are not present.
Additional information
The issue is here:
Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection::_getLoadAttributesSelect
lines 177-179:
if ($attribute->getAttributeCode() === 'price' && (int)$attribute->getIsGlobal() === 1) {
$storeId = $this->getDefaultStoreId();
}
it replaces $storeId with DefaultStoreId (0 - global) for attribute value select that's for all decimal attributes (not only price).
Without ->addAttributeToSelect('price')
returned select looks like this:
SELECT `t_d`.`attribute_id`, `e`.`entity_id` FROM `catalog_product_entity_decimal` AS `t_d`
INNER JOIN `catalog_product_entity` AS `e` ON e.entity_id = t_d.entity_id
LEFT JOIN `catalog_product_entity_decimal` AS `t_s` ON t_s.attribute_id = t_d.attribute_id AND t_s.entity_id = t_d.entity_id AND t_s.store_id = 1 WHERE (e.entity_id IN (2, 3)) AND (t_d.attribute_id IN (146)) AND (t_d.store_id = IFNULL(t_s.store_id, 0))
and has correct t_s.store_id = 1
and works as expected.
And if we add ->addAttributeToSelect('price')
to collection, returned select looks like this:
SELECT `t_d`.`attribute_id`, `e`.`entity_id` FROM `catalog_product_entity_decimal` AS `t_d`
INNER JOIN `catalog_product_entity` AS `e` ON e.entity_id = t_d.entity_id
LEFT JOIN `catalog_product_entity_decimal` AS `t_s` ON t_s.attribute_id = t_d.attribute_id AND t_s.entity_id = t_d.entity_id AND t_s.store_id = 0 WHERE (e.entity_id IN (2, 3)) AND (t_d.attribute_id IN (146, 77)) AND (t_d.store_id = IFNULL(t_s.store_id, 0))
with t_s.store_id = 0
which is wrong, because it wont load any other decimal attribute values that are scoped, or loaded values will be from global scope, even though $collection is for specific store_id.
Correct way to fix it is just to remove
Magento\Catalog\Model\ResourceModel\Collection\AbstractCollection::_getLoadAttributesSelect
lines 171-180:
foreach ($attributeIds as $id) {
$attribute = $this->_eavConfig->getAttribute(
$this->getEntity()->getType(),
$id
);
if ($attribute->getAttributeCode() === 'price' && (int)$attribute->getIsGlobal() === 1) {
$storeId = $this->getDefaultStoreId();
}
}
Because it's not neccessary
Then it works as expected.
Or check there if all attributes are global: $attribute->getIsGlobal() === 1
not only price.
Release note
No response
Triage and priority
- Severity: S0 - Affects critical data or functionality and leaves users without workaround.
- Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
- Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
- Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
- Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status