Атрибут сортировки Magento по десятичной системе не алфавитно
Итак, я схожу с ума, как сумасшедший, чтобы попытаться найти решение этой проблемы, которая действительно работает правильно, но пришла с пустыми руками.
При использовании функции Sort By на странице категории для сортировки товаров по атрибуту (емкость, вес и т.д.). Magento подобен этому, потому что он считает, что это текстовая строка:
Продукт A: 10 кг
Продукт B: 11 кг
Продукт C: 15 кг
Продукт D: 9 кг
тогда как он должен выглядеть следующим образом:
Продукт D: 9 кг
Продукт A: 10 кг
Продукт B: 11 кг
Продукт C: 15 кг
Оглядываясь, кажется, что люди предлагают изменить backend_type на десятичные и frontend_input на цену в таблице eav_attribute для атрибутов, которые вы бы как сортировать численно. Однако это не только не работает, но и изменяет формат номера, чтобы иметь перед ним символ доллара ($), и потому, что мы отображаем фактическое значение атрибута на странице продукта, поверх его использования для сортировки, мы не работаем как исправление.
Я пытаюсь выяснить, как работает метод getSortOrder(), но похоже, что эта функциональность довольно глубоко встроена, поэтому я изо всех сил пытаюсь найти способ обхода этой ошибки.
Любая помощь приветствуется!
EDIT:
Для тех, кто хочет решить эту проблему в будущем, здесь исправление, которое я придумал:
Вам нужно переопределить функцию _getProductCollection() в List.php, которая хранится в приложении /Code/Mage/core/catalog/block/product/list.php.
Скопируйте файл в приложение/код/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....
Теперь, если у вас есть входная проверка для владельца магазина в панели администратора для атрибута, установленного на Десятичный номер или целочисленный номер:
Тогда этот код будет reset порядок сортировки в коллекции продуктов, а затем CAST его как целое число со знаком, так что он будет сортироваться численно, а не буквенно-цифровым способом.
Надеюсь, что это поможет кому-то!
Ответы
Ответ 1
Итак, я нашел поток в этом в своей документации и, по-видимому, это известная точка боли для продукта. Лучшее решение, которое я нашел, состояло в том, чтобы переопределить 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'));
Ответ 2
В ответ на пост Адама Б.
Моя ситуация: мне нужно было сортировать продукты по специальному атрибуту 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));
Надеюсь, что это кому-то понравится.
Ответ 3
Можете ли вы рассказать нам "Catalog Input Type for Store Owner
"? Например, это текст или выпадаете? Я имею в виду, у вас есть столбец "position" в Magento Admin (Catalog- > Attributes- > Manage attributes- > Manage Label/Options- > Manage Options (значения вашего атрибута)). Если ваш атрибут является текстом, является ли фактическое значение строкой '9kg'
или она '9'
с 'kg'
добавлена позже?
В любом случае, если вы можете установить позицию в редакторе атрибутов, я думаю, что getSortOrder()
поможет вам (подтвердите это, и кто-то может опубликовать ответ о getSortOrder()
).
Если вы не можете установить позицию (потому что значения не заданы заранее), я думаю, вам нужно будет создать порядок сортировки продукта самостоятельно *, возможно, удалив буквы из значений атрибутов с помощью preg_replace()
или str_replace()
, сортируя по результату этого, а затем передавая новый отсортированный массив продуктов в циклы отображения - см. "грубый псевдокод" в этом ответе.
*, потому что я не думаю, что какие-либо встроенные общие функции сортировки могут сказать, что строка '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 может заключаться в том, чтобы добавить XML-код, который определяет новый тип ввода для Catalog Input Type for Store Owner
, но я оставил бы это в основных разработчиках Magento - возможно, у них есть веская причина для хранения значений атрибутов в виде строк.
Если вы используете системный атрибут 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){
//...
Это может быть полезно. Я не думаю, что вам потребуется много времени, чтобы закодировать свой собственный вид.
Ответ 4
Относительно ситуации "Атрибут с числовым значением" выше. У меня была та же проблема, и я сделал добавление кероса "0" перед моими значениями.
Например, мои значения: 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/
Надеюсь на эту помощь!
Ответ 5
Извините, я немного опаздываю на обсуждение.
Поскольку я не против реализации программных решений, когда это не является строго необходимым, я попытался придумать более легкое решение. Я придумал следующее.
Пример сортировки проблем
Исходный порядок сортировки: 10,0 ", 10,5", 14,0 ", 8,0", 8,5 "
Учитывая, что список чисел сортируется буквенно-цифровым образом, я решил, что добавление символов смещения пробела ("") до 8s в моем примере выше должно привести к правильному порядку. Так оно и было. Это было результатом.
Пример правильной сортировки
Новый порядок сортировки: 8,0 ", 8,5", 10,0 ", 10,5", 14,0 "
В OP Адам мог бы просто заменить "9 кг" на "9 кг".
В добавлении, если рассматриваемые числа варьируются от одних значений до сотен значений, те значения будут иметь 2 ведущие пробелы, значения десятков будут иметь 1 начальное пространство и т.д.
Ответ 6
Для порядка сортировки по умолчанию:
// 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');