Magento 1.9.1 not sorting Configurable product attributes dropdown by position

后端 未结 5 1486
庸人自扰
庸人自扰 2021-02-20 04:42

Fresh install of Magento 1.9.1.

Magento is ignoring the attribute position set in Catalogue->Attributes->Manage Attributes->Manage Labels/Options for a configurable prod

5条回答
  •  南旧
    南旧 (楼主)
    2021-02-20 05:36

    Just to add my two cents, the other two answers did well to point me in fix's direction, but I thought I'd attack it at the source rather than the block presentation point.

    You can achieve the same result by extending the Mage_Catalog_Model_Resource_Product_Type_Configurable_Attribute_Collection model's _loadPrices() method, which despite the name is where a change was made (presumably for performance) resulting in the attributes being ordered by ID rather than by relevance.

    The change appears to have been made to avoid nested foreach statements, but in turn loses the correct order as well. This solution modifies the updated logic slightly to track the attribute options, then performs another loop based on the original order to actually do the adding.

    Here's an adjusted walkthrough similar to meogi's answer above:


    Step 1: Register a new module

    Note: if you already have one, re-use an existing one.

    # File: app/etc/modules/YourCompany_AttributeFix.xml
    
    
        
            
                true
                local
                
                    
                
            
        
    
    

    Step 2: Create the module's configuration

    # File: app/code/local/YourCompany/AttributeFix/etc/config.xml
    
    
        
            
                0.1.0
            
            
        
            
                
                    
                        YourCompany_AttributeFix_Model_Resource_Product_Type_Configurable_Attribute_Collection
                    
                
            
        
    
    

    Step 3: Add the resource model extension

    # File: app/code/local/YourCompany/AttributeFix/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
    /**
     * Catalog Configurable Product Attribute Collection - overridden to re-enable the attribute option
     * sorting by relevance rather than by ID as changed in the Magento core class
     */
    class YourCompany_AttributeFix_Model_Resource_Product_Type_Configurable_Attribute_Collection
        extends Mage_Catalog_Model_Resource_Product_Type_Configurable_Attribute_Collection
    {
        /**
         * Load attribute prices information
         *
         * @return Mage_Catalog_Model_Resource_Product_Type_Configurable_Attribute_Collection
         */
        protected function _loadPrices()
        {
            if ($this->count()) {
                $pricings = array(
                    0 => array()
                );
    
                if ($this->getHelper()->isPriceGlobal()) {
                    $websiteId = 0;
                } else {
                    $websiteId = (int)Mage::app()->getStore($this->getStoreId())->getWebsiteId();
                    $pricing[$websiteId] = array();
                }
    
                $select = $this->getConnection()->select()
                    ->from(array('price' => $this->_priceTable))
                    ->where('price.product_super_attribute_id IN (?)', array_keys($this->_items));
    
                if ($websiteId > 0) {
                    $select->where('price.website_id IN(?)', array(0, $websiteId));
                } else {
                    $select->where('price.website_id = ?', 0);
                }
    
                $query = $this->getConnection()->query($select);
    
                while ($row = $query->fetch()) {
                    $pricings[(int)$row['website_id']][] = $row;
                }
    
                $values = array();
    
                foreach ($this->_items as $item) {
                    $productAttribute = $item->getProductAttribute();
                    if (!($productAttribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract)) {
                        continue;
                    }
                    $options = $productAttribute->getFrontend()->getSelectOptions();
    
                    $optionsByValue = array();
                    foreach ($options as $option) {
                        $optionsByValue[$option['value']] = $option['label'];
                    }
    
                    /**
                     * Modification to re-enable the sorting by relevance for attribute options
                     * @author Robbie Averill 
                     */
                    $toAdd = array();
                    foreach ($this->getProduct()->getTypeInstance(true)
                                 ->getUsedProducts(array($productAttribute->getAttributeCode()), $this->getProduct())
                             as $associatedProduct) {
    
                        $optionValue = $associatedProduct->getData($productAttribute->getAttributeCode());
    
                        if (array_key_exists($optionValue, $optionsByValue)) {
                            $toAdd[] = $optionValue;
                        }
                    }
    
                    // Add the attribute options, but in the relevant order rather than by ID
                    foreach (array_intersect_key($optionsByValue, array_flip($toAdd)) as $optionValueKey => $optionValue) {
                        // If option available in associated product
                        if (!isset($values[$item->getId() . ':' . $optionValue])) {
                            // If option not added, we will add it.
                            $values[$item->getId() . ':' . $optionValueKey] = array(
                                'product_super_attribute_id' => $item->getId(),
                                'value_index'                => $optionValueKey,
                                'label'                      => $optionsByValue[$optionValueKey],
                                'default_label'              => $optionsByValue[$optionValueKey],
                                'store_label'                => $optionsByValue[$optionValueKey],
                                'is_percent'                 => 0,
                                'pricing_value'              => null,
                                'use_default_value'          => true
                            );
                        }
                    }
                    /**
                     * End attribute option order modification
                     * @author Robbie Averill 
                     */
                }
    
                foreach ($pricings[0] as $pricing) {
                    // Affffding pricing to options
                    $valueKey = $pricing['product_super_attribute_id'] . ':' . $pricing['value_index'];
                    if (isset($values[$valueKey])) {
                        $values[$valueKey]['pricing_value']     = $pricing['pricing_value'];
                        $values[$valueKey]['is_percent']        = $pricing['is_percent'];
                        $values[$valueKey]['value_id']          = $pricing['value_id'];
                        $values[$valueKey]['use_default_value'] = true;
                    }
                }
    
                if ($websiteId && isset($pricings[$websiteId])) {
                    foreach ($pricings[$websiteId] as $pricing) {
                        $valueKey = $pricing['product_super_attribute_id'] . ':' . $pricing['value_index'];
                        if (isset($values[$valueKey])) {
                            $values[$valueKey]['pricing_value']     = $pricing['pricing_value'];
                            $values[$valueKey]['is_percent']        = $pricing['is_percent'];
                            $values[$valueKey]['value_id']          = $pricing['value_id'];
                            $values[$valueKey]['use_default_value'] = false;
                        }
                    }
                }
    
                foreach ($values as $data) {
                    $this->getItemById($data['product_super_attribute_id'])->addPrice($data);
                }
            }
            return $this;
        }
    }
    

    Step 4: Clear your cache


    For reference, the actual change to the core class in a git diff would be below (do not directly edit core files!):

    diff --git a/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php b/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
    index 135d9d3..4d2a59b 100644
    --- a/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
    +++ b/app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
    @@ -254,6 +254,11 @@ class Mage_Catalog_Model_Resource_Product_Type_Configurable_Attribute_Collection
                         $optionsByValue[$option['value']] = $option['label'];
                     }
    
    +                /**
    +                 * Modification to re-enable the sorting by relevance for attribute options
    +                 * @author Robbie Averill 
    +                 */
    +                $toAdd = array();
                     foreach ($this->getProduct()->getTypeInstance(true)
                                  ->getUsedProducts(array($productAttribute->getAttributeCode()), $this->getProduct())
                              as $associatedProduct) {
    @@ -261,22 +266,31 @@ class Mage_Catalog_Model_Resource_Product_Type_Configurable_Attribute_Collection
                         $optionValue = $associatedProduct->getData($productAttribute->getAttributeCode());
    
                         if (array_key_exists($optionValue, $optionsByValue)) {
    -                        // If option available in associated product
    -                        if (!isset($values[$item->getId() . ':' . $optionValue])) {
    -                            // If option not added, we will add it.
    -                            $values[$item->getId() . ':' . $optionValue] = array(
    -                                'product_super_attribute_id' => $item->getId(),
    -                                'value_index'                => $optionValue,
    -                                'label'                      => $optionsByValue[$optionValue],
    -                                'default_label'              => $optionsByValue[$optionValue],
    -                                'store_label'                => $optionsByValue[$optionValue],
    -                                'is_percent'                 => 0,
    -                                'pricing_value'              => null,
    -                                'use_default_value'          => true
    -                            );
    -                        }
    +                        $toAdd[] = $optionValue;
                         }
                     }
    +
    +                // Add the attribute options, but in the relevant order rather than by ID
    +                foreach (array_intersect_key($optionsByValue, array_flip($toAdd)) as $optionValueKey => $optionValue) {
    +                    // If option available in associated product
    +                    if (!isset($values[$item->getId() . ':' . $optionValue])) {
    +                        // If option not added, we will add it.
    +                        $values[$item->getId() . ':' . $optionValueKey] = array(
    +                            'product_super_attribute_id' => $item->getId(),
    +                            'value_index'                => $optionValueKey,
    +                            'label'                      => $optionsByValue[$optionValueKey],
    +                            'default_label'              => $optionsByValue[$optionValueKey],
    +                            'store_label'                => $optionsByValue[$optionValueKey],
    +                            'is_percent'                 => 0,
    +                            'pricing_value'              => null,
    +                            'use_default_value'          => true
    +                        );
    +                    }
    +                }
    +                /**
    +                 * End attribute option order modification
    +                 * @author Robbie Averill 
    +                 */
                 }
    
                 foreach ($pricings[0] as $pricing) {
    

    This is also on GitHub if anyone wants it for reference.

    Edit: I've also logged this as a bug with Magento.

提交回复
热议问题