Magento 1.9.1不按位置排序可配置产品属性下拉列表

hej*_*hog 11 sorting attributes position magento

全新安装Magento 1.9.1.

Magento忽略了Catalogue-> Attributes-> Manage Attributes-> Manage Labels/Options中为可配置产品下拉列表设置的属性位置.相反,它使用产品ID来确定列表顺序.

比较了以下文件/功能,除了小额税收计算外,自1.7.0.2以来,没有任何代码发生过变化.

法师/目录/型号/产品/类型/ Configuarable.php:

public function getConfigurableAttributes($product = null)
Run Code Online (Sandbox Code Playgroud)

法师/目录/型号/产品/ Option.php:

public function getProductOptionCollection(Mage_Catalog_Model_Product $product)
Run Code Online (Sandbox Code Playgroud)

法师/目录/座/产品/浏览/类型/ Configuarable.php:

public function getJsonConfig()
Run Code Online (Sandbox Code Playgroud)

我还在一个实时网站的副本数据库上进行了测试,所有属性排序都基于产品ID.

复制:

  1. 创建属性 - 颜色
  2. 添加标签 - 黑色,红色,绿色,蓝色
  3. 保存属性.
  4. 使用上述顺序的属性创建可配置且简单的关联产品.

编辑属性并更改标签位置.蓝色0,绿色1,红色3,黑色4

查看产品时,Magento仍会按产品ID对属性进行排序,并忽略位置.

小智 15

Meogi的答案有效,但不是完美的答案,因为它只会对前端的选项进行排序.尝试从管理面板为可配置产品创建订单.您仍将获得错误排序的属性选项列表.

相反,您可以将app/code/core/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php复制到本地文件夹app/code/local/Mage/Catalog/Model/Resource/Product/Type /Configurable/Attribute/Collection.php并应用此补丁:

Index: app/code/local/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
===================================================================
--- app/code/local/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
+++ app/code/local/Mage/Catalog/Model/Resource/Product/Type/Configurable/Attribute/Collection.php
@@ -301,7 +301,28 @@
                     }
                 }
             }

+            /**
+             * Mage 1.9+ fix for configurable attribute options not sorting to position
+             * @author Harshit <support@cubixws.co.uk>
+             */
+            $sortOrder = 1;
+            foreach ($this->_items as $item) {
+                $productAttribute = $item->getProductAttribute();
+                if (!($productAttribute instanceof Mage_Eav_Model_Entity_Attribute_Abstract)) {
+                    continue;
+                }
+                $options = $productAttribute->getFrontend()->getSelectOptions();
+                foreach ($options as $option) {
+                    if (!$option['value']) {
                         continue;
                     }

+                    if (isset($values[$item->getId() . ':' . $option['value']])) {
+                        $values[$item->getId() . ':' . $option['value']]['order'] = $sortOrder++;
+                    }
+                }
+            }
+            usort($values, function ($a, $b) {
+                return $a['order'] - $b['order'];
+            });
+            
             foreach ($values as $data) {
                 $this->getItemById($data['product_super_attribute_id'])->addPrice($data);
             }
Run Code Online (Sandbox Code Playgroud)

如果您对将核心文件复制到本地文件夹犹豫不决,那么我可以创建一个快速模块,<rewrite>这个Collection.php文件,只需覆盖_loadPrices()函数并引入此修复程序.

  • @Harshit,谢谢你的解决方案.对于想要它的人,我把它放在一个模块[这里](https://github.com/rossmc/SwatchSorting)中. (3认同)
  • 我修补了文件并为那些不知道如何操作的人创建了一个步骤http://magentosupport.help/knowledgebase/solved-sort-configurable-product-attribute-options-and-dropdowns/ (2认同)

Dar*_*ton 7

注意:此处列出的解决方案扩展了Magento核心库中的块类文件.我在此方法之前审查了Magento的源代码,并确定没有一个好的事件要遵守以避免这种方法.如果在未来版本的Magento中解决了这个排序问题,您可以通过在其app/etc/modules XML文件中禁用扩展来撤消这些更改.

第1步:创建文件app/etc/modules/FirstScribe_CatalogOptionSortFix.xml

内容:

<?xml version="1.0"?>
<config>
    <modules>
        <FirstScribe_CatalogOptionSortFix>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Catalog />
            </depends>
        </FirstScribe_CatalogOptionSortFix>
    </modules>
</config>
Run Code Online (Sandbox Code Playgroud)

注意:对于步骤2和3,根据需要为这些文件创建目录.例如,您可能已经拥有目录app/code/local,或者您可能没有,具体取决于您在网站上已安装的扩展程序.

第2步:创建文件app/code/local/FirstScribe/CatalogOptionSortFix/etc/config.xml

内容:

<?xml version="1.0"?>
<!--
/**
 * Magento 1.9.1.0 has a bug in that the configurable options are sorted by
 * ID rather than position for the Configurable Product's front end view script.
 * This extension addresses this problem.
 *
 * @category    FirstScribe
 * @package     FirstScribe_CatalogOptionSortFix
 * @version     2014.12.15
 */
-->
<config>
    <modules>
        <FirstScribe_CatalogOptionSortFix>
            <version>1.0.0</version>
        </FirstScribe_CatalogOptionSortFix>
    </modules>
    <global>
        <blocks>
            <catalog>
                <rewrite>
                    <product_view_type_configurable>FirstScribe_CatalogOptionSortFix_Block_Product_View_Type_Configurable</product_view_type_configurable>
                </rewrite>
            </catalog>
        </blocks>
    </global>
</config>
Run Code Online (Sandbox Code Playgroud)

第3步:创建文件app/code/local/FirstScribe/CatalogOptionSortFix/Block/Product/View/Type/Configurable.php

内容:

<?php
/**
 * Magento 1.9.1.0 has a bug in that the configurable options are sorted by
 * ID rather than position for the Configurable Product's front end view script.
 * This extension addresses this problem.
 *
 * @category    FirstScribe
 * @package     FirstScribe_CatalogOptionSortFix
 * @version     2014.12.15
 */
class FirstScribe_CatalogOptionSortFix_Block_Product_View_Type_Configurable extends Mage_Catalog_Block_Product_View_Type_Configurable
{
    /**
     * @var Magento_Db_Adapter_Pdo_Mysql
     */
    protected $_read;

    /**
     * @var string
     */
    protected $_tbl_eav_attribute_option;

    /**
     * Composes configuration for js
     *
     * @version 2014.12.15 - Addition of this line:
     *    $info['options'] = $this->_sortOptions($info['options']);
     *
     * @return string
     */
    public function getJsonConfig()
    {
        $attributes = array();
        $options    = array();
        $store      = $this->getCurrentStore();
        $taxHelper  = Mage::helper('tax');
        $currentProduct = $this->getProduct();

        $preconfiguredFlag = $currentProduct->hasPreconfiguredValues();
        if ($preconfiguredFlag) {
            $preconfiguredValues = $currentProduct->getPreconfiguredValues();
            $defaultValues       = array();
        }

        foreach ($this->getAllowProducts() as $product) {
            $productId  = $product->getId();

            foreach ($this->getAllowAttributes() as $attribute) {
                $productAttribute   = $attribute->getProductAttribute();
                $productAttributeId = $productAttribute->getId();
                $attributeValue     = $product->getData($productAttribute->getAttributeCode());
                if (!isset($options[$productAttributeId])) {
                    $options[$productAttributeId] = array();
                }

                if (!isset($options[$productAttributeId][$attributeValue])) {
                    $options[$productAttributeId][$attributeValue] = array();
                }
                $options[$productAttributeId][$attributeValue][] = $productId;
            }
        }

        $this->_resPrices = array(
            $this->_preparePrice($currentProduct->getFinalPrice())
        );

        foreach ($this->getAllowAttributes() as $attribute) {
            $productAttribute = $attribute->getProductAttribute();
            $attributeId = $productAttribute->getId();
            $info = array(
                    'id'        => $productAttribute->getId(),
                    'code'      => $productAttribute->getAttributeCode(),
                    'label'     => $attribute->getLabel(),
                    'options'   => array()
            );

            $optionPrices = array();
            $prices = $attribute->getPrices();
            if (is_array($prices)) {
                foreach ($prices as $value) {
                    if(!$this->_validateAttributeValue($attributeId, $value, $options)) {
                        continue;
                    }
                    $currentProduct->setConfigurablePrice(
                            $this->_preparePrice($value['pricing_value'], $value['is_percent'])
                    );
                    $currentProduct->setParentId(true);
                    Mage::dispatchEvent(
                            'catalog_product_type_configurable_price',
                            array('product' => $currentProduct)
                    );
                    $configurablePrice = $currentProduct->getConfigurablePrice();

                    if (isset($options[$attributeId][$value['value_index']])) {
                        $productsIndex = $options[$attributeId][$value['value_index']];
                    } else {
                        $productsIndex = array();
                    }

                    $info['options'][] = array(
                            'id'        => $value['value_index'],
                            'label'     => $value['label'],
                            'price'     => $configurablePrice,
                            'oldPrice'  => $this->_prepareOldPrice($value['pricing_value'], $value['is_percent']),
                            'products'  => $productsIndex,
                    );
                    $optionPrices[] = $configurablePrice;
                }
            }

            // CALL SORT ORDER FIX
            $info['options'] = $this->_sortOptions($info['options']);

            /**
             * Prepare formated values for options choose
             */
            foreach ($optionPrices as $optionPrice) {
                foreach ($optionPrices as $additional) {
                    $this->_preparePrice(abs($additional-$optionPrice));
                }
            }
            if($this->_validateAttributeInfo($info)) {
                $attributes[$attributeId] = $info;
            }

            // Add attribute default value (if set)
            if ($preconfiguredFlag) {
                $configValue = $preconfiguredValues->getData('super_attribute/' . $attributeId);
                if ($configValue) {
                    $defaultValues[$attributeId] = $configValue;
                }
            }
        }

        $taxCalculation = Mage::getSingleton('tax/calculation');
        if (!$taxCalculation->getCustomer() && Mage::registry('current_customer')) {
            $taxCalculation->setCustomer(Mage::registry('current_customer'));
        }

        $_request = $taxCalculation->getDefaultRateRequest();
        $_request->setProductClassId($currentProduct->getTaxClassId());
        $defaultTax = $taxCalculation->getRate($_request);

        $_request = $taxCalculation->getRateRequest();
        $_request->setProductClassId($currentProduct->getTaxClassId());
        $currentTax = $taxCalculation->getRate($_request);

        $taxConfig = array(
                'includeTax'        => $taxHelper->priceIncludesTax(),
                'showIncludeTax'    => $taxHelper->displayPriceIncludingTax(),
                'showBothPrices'    => $taxHelper->displayBothPrices(),
                'defaultTax'        => $defaultTax,
                'currentTax'        => $currentTax,
                'inclTaxTitle'      => Mage::helper('catalog')->__('Incl. Tax')
        );

        $config = array(
                'attributes'        => $attributes,
                'template'          => str_replace('%s', '#{price}', $store->getCurrentCurrency()->getOutputFormat()),
                'basePrice'         => $this->_registerJsPrice($this->_convertPrice($currentProduct->getFinalPrice())),
                'oldPrice'          => $this->_registerJsPrice($this->_convertPrice($currentProduct->getPrice())),
                'productId'         => $currentProduct->getId(),
                'chooseText'        => Mage::helper('catalog')->__('Choose an Option...'),
                'taxConfig'         => $taxConfig
        );

        if ($preconfiguredFlag && !empty($defaultValues)) {
            $config['defaultValues'] = $defaultValues;
        }

        $config = array_merge($config, $this->_getAdditionalConfig());    

        return Mage::helper('core')->jsonEncode($config);
    }

    /**
     * Sort the options based off their position.
     *
     * @param array $options
     * @return array
     */
    protected function _sortOptions($options)
    {
        if (count($options)) {
            if (!$this->_read || !$this->_tbl_eav_attribute_option) {
                $resource = Mage::getSingleton('core/resource');

                $this->_read = $resource->getConnection('core_read');
                $this->_tbl_eav_attribute_option = $resource->getTableName('eav_attribute_option');
            }

            // Gather the option_id for all our current options
            $option_ids = array();
            foreach ($options as $option) {
                $option_ids[] = $option['id'];

                $var_name  = 'option_id_'.$option['id'];
                $$var_name = $option;
            }

            $sql    = "SELECT `option_id` FROM `{$this->_tbl_eav_attribute_option}` WHERE `option_id` IN('".implode('\',\'', $option_ids)."') ORDER BY `sort_order`";
            $result = $this->_read->fetchCol($sql);

            $options = array();
            foreach ($result as $option_id) {
                $var_name  = 'option_id_'.$option_id;
                $options[] = $$var_name;
            }
        }

        return $options;
    }
}
Run Code Online (Sandbox Code Playgroud)

步骤4:如果启用,请在管理面板的系统 - >缓存管理下刷新Magento的"配置"缓存类型.

扩展概述

  1. 扩展Mage_Catalog_Block_Product_View_Type_Configurable类.
  2. position通过从数据库中提取此信息,添加一个方法,以按值对选项进行排序.
  3. 在收集了属性的选项后,重写getJsonConfig方法以调用我们的新函数.

  • @Joe您的欢迎.有关更新的反馈 - 解决方案是以某种方式编写的,这样一旦Magento的核心团队在更新中修复了问题,我们所要做的就是在`app/etc/modules/FirstScribe_CatalogOptionSortFix.xml`中禁用此扩展,一切都会回来使用核心Mage类,不再重写核心类. (2认同)