Magento按十进制排序属性不是字母数字

时间:2014-03-07 20:51:22

标签: php sql magento sorting

所以我用谷歌搜索疯狂试图找到一个解决方案来解决这个问题,这个问题实际上是正常的,但却是空手而归。

在类别页面上使用“排序依据”功能时,可以按属性(容量,重量等)对产品进行排序。 Magento这样排序,因为它认为数字是一个文本字符串:

  

产品A:10kg

     

产品B:11kg

     

产品C:15kg

     

产品D:9kg

然而它应该类似于:

  

产品D:9kg

     

产品A:10kg

     

产品B:11kg

     

产品C:15kg

环顾四周似乎人们建议将 backend_type 更改为十进制,将 frontend_input 更改为 eav_attribute 表格中的属性喜欢用数字排序。但是,这不仅实际上不起作用,而且它改变了数字的格式,在它前面有一个美元($)符号,因为我们在产品页面上显示实际属性值,在使用它之上为了排序,我们不能解决问题。

我正在试图弄清楚getSortOrder()方法是如何工作的,但看起来这个功能非常深入,所以我很难为这个bug找到解决方法。

感谢任何帮助!

修改

对于那些希望将来解决这个问题的人来说,这是我提出的解决方案:

您需要覆盖List.php中存储在app / Code / Mage / core / catalog / block / product / list.php中的函数_getProductCollection()。 将文件复制到app / code / Mage / local / catalog / block / product / list.php,这样就不会编辑核心文件。

然后在下面的地方说:

$this->_productCollection = $layer->getProductCollection();

输入以下代码:

        // Start of Code to force Magento to numerically sort decimal attributes rather than alphabetically

        $filterAttribute = $this->getRequest()->getParam('order');
        $filterAttributeDir = $this->getRequest()->getParam('dir');
        $attributeType = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $filterAttribute)->getFrontendClass();

        // If a Sort By option is selected on category page and attribute has frontend_class = validate-number or validate-digits 
        // then CAST the attribute values as signed integers

        if (isset($filterAttribute) && ($attributeType == 'validate-digits' || $attributeType == 'validate-number')) {

            $this->_productCollection->getSelect()->reset(Zend_Db_Select::ORDER);
            $this->_productCollection->getSelect()->order('CAST(`' . $filterAttribute . '` AS SIGNED) ' . $filterAttributeDir . "'");

        }

        // End of code to force Magento to numerically sort....

现在,如果您在管理面板中为存储所有者的输入验证设置为十进制数或整数数:  attribute type 然后,此代码将重置产品集合上的排序顺序,然后将其作为有符号整数进行CAST,以便按数字而不是字母数字进行排序。

希望能帮助别人!

6 个答案:

答案 0 :(得分:12)

所以我在他们的文档中找到了thread on this,显然这是该产品的一个已知的痛点。我找到的最佳解决方案是通过调用ORDER BY类的基本方法来覆盖查询的Collection,这是他们提供的示例:

$_productCollection = Mage::getModel('catalog/product')->getCollection();

$_productCollection->setOrder(array('cm_brand', 'name', 'cm_length'), 'asc');
$_productCollection->getSelect()->reset(Zend_Db_Select::ORDER);
$_productCollection->getSelect()->order(array('cm_brand ASC', 'name ASC', 'CAST(`cm_length` AS SIGNED) ASC'));

根据您的示例只有一个排序列,我认为您可以选择:

$_productCollection = Mage::getModel('catalog/product')->getCollection();
$_productCollection->setOrder('weight', 'asc');
$_productCollection->getSelect()->reset(Zend_Db_Select::ORDER);
$_productCollection->getSelect()->order('CAST(`weight` AS SIGNED) ASC'));

答案 1 :(得分:2)

回应Adam B的帖子。

我的情况:我需要使用带有数值的自定义Magento(1.8.1.0)属性对产品进行排序。但是,Magento的排序方式如下:

1 , 11 , 123 ,2 ,234, 3(字母数字) 而不是:1, 2, 3, 11, 123, 234(数字)

老实说,我不明白为什么这不是开箱即用的工具,但我的工作方式如下:

$this->_productCollection->getSelect()->order(new Zend_Db_Expr("CAST( ".$filterAttribute." AS SIGNED ) ".$filterAttributeDir));

希望有人使用它。

答案 2 :(得分:0)

你能告诉我们'Catalog Input Type for Store Owner'吗?例如是文字还是下拉?我的意思是,你在Magento Admin中有一个“位置”列(目录 - >属性 - >管理属性 - >管理标签/选项 - >管理选项(属性值))。如果您的属性是文本,那么实际值是字符串'9kg',还是'9'后面添加了'kg'

无论如何,如果你可以在属性编辑器中设置一个位置,那么我认为getSortOrder()会帮助你(确认这一点,有人可以发表关于getSortOrder()的答案。)

如果您无法设置位置(因为这些值未预先确定),那么我认为您需要自己创建产品排序顺序*可能需要使用preg_replace()从属性值中删除字母或str_replace(),对结果进行排序,然后passing the new sorted product array into the display loop - see 'rough pseudo code' in this answer

*因为我认为任何内置的通用排序函数都不能告诉字符串'9kg'小于字符串'11kg''3V'小于'18V'

**编辑后评论:

啊,是的,我看到Magento没有Catalog Input Type for Store Owner的数字输入类型。我认为你应该在.phtml或相关的块php类中编码你自己的排序(或者如果你事先知道权重使它成为一个下拉列表,例如1,2,3,4 ...或1.1,1.2,1.3 .. .4.1,4.2,4.3 ...... 19.9)那么你可以告诉Magento这个位置。

您可能会使用Date输入类型甚至是Fixed product tax输入类型,但我认为这会导致问题(以及大量测试)。

计划B可能是添加一些为Catalog Input Type for Store Owner定义新数字输入类型的XML,但我将其留给核心Magento开发人员 - 也许他们有充分的理由将属性值存储为字符串。< / p>

如果您正在使用系统属性Weight,那么它将被修复为输入类型text,我认为您除了编码自己的排序外别无选择。

我刚刚找到

//file: app/code/core/Mage/Core/Model/Locale.php
//class: Mage_Core_Model_Locale
//...
     /*
     * @param string|float|int $value
     * @return float|null
     */
    public function getNumber($value){
//...

哪个可能有用。我不认为你需要很长时间来编写自己的代码。

答案 3 :(得分:0)

关于&#34;具有数值的属性&#34;上面的情况。我有同样的问题,我做的是添加ceros&#34; 0&#34;在我的价值观面前。

对于前者,我的价值观是:208,209,355,1152和1153.

我添加了ceros:00208,00209,00355,01152和01153。

现在有效!

这篇文章也对我有所帮助:

http://blog.adin.pro/2014-04-30/magento-custom-sort-on-grid-sort-increment_id-by-numeric-not-alpha/

希望这有帮助!

答案 4 :(得分:0)

对不起,我讨论的时间有点晚了。 由于在不是绝对必要的情况下我不能实现代码解决方案,我试着想出一个更简单的解决方案。我想出了以下内容。

问题排序示例 原始排序顺序:10.0“,10.5”,14.0“,8.0”,8.5“

鉴于数字列表按字母顺序排序,我推断在上面的示例中在8s之前添加偏移空格字符(“”)应该导致正确的排序。它做了。这就是结果。

示例正确排序 新的排序顺序:8.0“,8.5”,10.0“,10.5”,14.0“

在OP中,Adam可能很简单地能够用“9kg”代替“9kg”。

通过扩展,如果有问题的数字从一个值到数百个值,那些值将具有2个前导空格,十个值将具有1个前导空格等。

答案 5 :(得分:0)

对于默认排序顺序:

        // Start of Code to force Magento to numerically sort decimal attributes rather than alphabetically
        $filterAttribute = Mage::getBlockSingleton('catalog/product_list_toolbar')->getCurrentOrder();
        //$filterAttribute = $this->getRequest()->getParam('order');
        $filterAttributeDir = Mage::getBlockSingleton('catalog/product_list_toolbar')->getCurrentDirection();
        //$filterAttributeDir = $this->getRequest()->getParam('dir');