cancel
Showing results for 
Search instead for 
Did you mean: 

Сортировка по нескольким атрибутам

Сортировка по нескольким атрибутам

Подскажите как сделать сортировку товаров сразу по двум атрибутам, т.е. аналог SQL запроса

 

ORDER BY
   sku ASC,
   name DESC

Подозреваю, что надо поправить что-то тут:

 

app/design/frontend/default/default/template/catalog/product/list.phtml

 

Но что конкретно нагуглить так и не удалось (

 

Соответственно нужно отключить выбор типа сортировки в теме, это как сделать вообще не нашел.

 

Заранее благодарен

8 REPLIES 8

Re: Сортировка по нескольким атрибутам

Шаблона мало. Надо править блоки. Точнее можно сделать оверрайд блока Mage_Catalog_Block_Product_List поменяв метод _getProductCollection(). Шаблон кстати при этом трогать вообще не надо.

Re: Сортировка по нескольким атрибутам

evmedvedev, спасибо за совет!

 

Можно чуть-чуть подробнее? Я в Magento новичек, уж простите )

 

Где мне найти блок Mage_Catalog_Block_Product_List ? И не хотелось бы конечно в core лезть, чтобы при обновлении не слетело, как правильно в magento override сделать?

 

Заранее благодарен!!!

Re: Сортировка по нескольким атрибутам

Тогда вам будет не просто разобраться. Вообще указанный файл нужно искать в /app/code/core/Mage/Catalog/Block/Product и он там фигурирует как List.php (в нем и декларируется класс Mage_Catalog_Block_Product_List). Как видите приведенный выше класс формируется из /Mage/Catalog/Block/Product заменой слэшей на "_" и добавлением через него же List. Такой подход к организации кода заложен в Zend Framework на котором и построен движок и который желательно изучить получше. Для замены функционала ядра без его перезаписывания нужно положить файл List.php в каталог /app/code/local/Mage/Catalog/Block/Product (обратите внимание на замену core на local) и после этого можете экспериментировать с указанными функциями.

Re: Сортировка по нескольким атрибутам

Спасибо, evmedvedev!

 

В принципе получается, подскажите только один нюанс:

 

В методе _getProductCollection перед

 

return $this->_productCollection;

добавляю

$this->_productCollection->getSelect()->reset( Zend_Db_Select::ORDER );
$this->_productCollection->getSelect()->joinLeft('eav_attribute_option', 'eav_attribute_option.option_id = e.seasons', array('eav_attribute_option.sort_order'));
$this->_productCollection->getSelect()->joinLeft('eav_attribute', join(' AND ', array('eav_attribute.attribute_code = "seasons"', 'eav_attribute.attribute_id = eav_attribute_option.attribute_id')), array());
$this->_productCollection->getSelect()->order(array('e.seasons DESC', 'e.importance ASC'));

Почему-то JOIN-ы он добавляет в запрос 2 раза:

 

SELECT 1 AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`, `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`, `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`, `e`.`news_to_date`, `e`.`url_key`, `e`.`required_options`, `e`.`image_label`, `e`.`small_image_label`, `e`.`thumbnail_label`, `e`.`msrp_enabled`, `e`.`msrp_display_actual_price_type`, `e`.`msrp`, `e`.`price_type`, `e`.`weight_type`, `e`.`price_view`, `e`.`shipment_type`, `e`.`links_purchased_separately`, `e`.`links_exist`, `e`.`razmery`, `e`.`manufacturer_my`, `e`.`manufacturer_my_value`, `e`.`color_my`, `e`.`razmer_chashechki_2`, `e`.`obhvat_pod_grudyu_my`, `e`.`seasons`, `e`.`seasons_value`, `e`.`importance`, `e`.`importance_value`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `eav_attribute_option`.`sort_order`, `eav_attribute_option`.`sort_order` FROM `catalog_product_flat_1` AS `e`
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id = '6'
 INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0
 LEFT JOIN `eav_attribute_option` ON eav_attribute_option.option_id = e.seasons
 LEFT JOIN `eav_attribute` ON eav_attribute.attribute_code = "seasons" AND eav_attribute.attribute_id = eav_attribute_option.attribute_id
 LEFT JOIN `eav_attribute_option` AS `eav_attribute_option_2` ON eav_attribute_option.option_id = e.seasons
 LEFT JOIN `eav_attribute` AS `eav_attribute_2` ON eav_attribute.attribute_code = "seasons" AND eav_attribute.attribute_id = eav_attribute_option.attribute_id ORDER BY `eav_attribute_option`.`sort_order` ASC, `e`.`importance_value` DESC, `cat_index_position` ASC, `cat_index`.`position` ASC LIMIT 12

Если бы он не добавлял JOIN по два раза, то получился бы такой запрос:

SELECT 1 AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`, `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`, `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`, `e`.`news_to_date`, `e`.`url_key`, `e`.`required_options`, `e`.`image_label`, `e`.`small_image_label`, `e`.`thumbnail_label`, `e`.`msrp_enabled`, `e`.`msrp_display_actual_price_type`, `e`.`msrp`, `e`.`price_type`, `e`.`weight_type`, `e`.`price_view`, `e`.`shipment_type`, `e`.`links_purchased_separately`, `e`.`links_exist`, `e`.`razmery`, `e`.`manufacturer_my`, `e`.`manufacturer_my_value`, `e`.`color_my`, `e`.`razmer_chashechki_2`, `e`.`obhvat_pod_grudyu_my`, `e`.`seasons`, `e`.`seasons_value`, `e`.`importance`, `e`.`importance_value`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `eav_attribute_option`.`sort_order`, `eav_attribute_option`.`sort_order` FROM `catalog_product_flat_1` AS `e`
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id = '6'
 INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0
 LEFT JOIN `eav_attribute_option` ON eav_attribute_option.option_id = e.seasons
 LEFT JOIN `eav_attribute` ON eav_attribute.attribute_code = "seasons" AND eav_attribute.attribute_id = eav_attribute_option.attribute_id
ORDER BY `eav_attribute_option`.`sort_order` ASC, `e`.`importance_value` DESC, `cat_index_position` ASC, `cat_index`.`position` ASC LIMIT 12

который работает на ура 

 

В чем косяк?

Re: Сортировка по нескольким атрибутам

Так ничего и не получилось ((

 

Mage/Catalog/Block/Product/List.php перестал мучать,

пробую зайти через

app/design/frontend/default/theme/template/catalog/product/list.phtml

 

таким образом:

 

$_productCollection=$this->getLoadedProductCollection();
$_productCollection->getSelect()->joinLeft('eav_attribute_option', 'eav_attribute_option.option_id = e.seasons', array('eav_attribute_option.sort_order'));
$_productCollection->getSelect()->joinLeft('eav_attribute', join(' AND ', array('eav_attribute.attribute_code = "seasons"', 'eav_attribute.attribute_id = eav_attribute_option.attribute_id')), array());
$_productCollection->getSelect()->reset( Zend_Db_Select::ORDER );
$_productCollection->getSelect()->order(array('eav_attribute_option.sort_order ASC', 'e.importance_value DESC'));

Получаю такую ошибку:

 

a:5:{i:0;s:836:"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'e.seasons' in 'on clause', query was: SELECT FLOOR((ROUND((e.min_price) * 1, 2)) / 1000) + 1 AS `range`, COUNT(*) AS `count` FROM `catalog_product_index_price` AS `e`
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id = '38'
 LEFT JOIN `eav_attribute_option` ON eav_attribute_option.option_id = e.seasons
 LEFT JOIN `eav_attribute` ON eav_attribute.attribute_code = "seasons" AND eav_attribute.attribute_id = eav_attribute_option.attribute_id WHERE ( e.website_id = '1' ) AND ( e.customer_group_id = 0) AND (e.min_price IS NOT NULL) GROUP BY FLOOR((ROUND((e.min_price) * 1, 2)) / 1000) + 1 ORDER BY FLOOR((ROUND((e.min_price) * 1, 2)) / 1000) + 1 ASC";i:1;s:5575:"#0 /var/htdocs/happymam.new/public_html/lib/Varien/Db/Statement/Pdo/Mysql.php(110): Zend_Db_Statement_Pdo->_execute(Array)

Откуда этот запрос взялся - вообще мне не понятно ((, потому что 

 

$fw = fopen('/var/htdocs/happymam.new/public_html/media/dump.txt', 'a');
			
ob_start();
var_dump($_productCollection->getSelect()->__toString());
fwrite($fw, "-------------------\n\n\n\n" . ob_get_contents());
ob_end_clean();
			
fclose($fw);

Дает такой результат:

 

SELECT 1 AS `status`, `e`.`entity_id`, `e`.`type_id`, `e`.`attribute_set_id`, `cat_index`.`position` AS `cat_index_position`, `e`.`name`, `e`.`short_description`, `e`.`sku`, `e`.`price`, `e`.`special_price`, `e`.`special_from_date`, `e`.`special_to_date`, `e`.`small_image`, `e`.`thumbnail`, `e`.`news_from_date`, `e`.`news_to_date`, `e`.`url_key`, `e`.`required_options`, `e`.`image_label`, `e`.`small_image_label`, `e`.`thumbnail_label`, `e`.`msrp_enabled`, `e`.`msrp_display_actual_price_type`, `e`.`msrp`, `e`.`price_type`, `e`.`weight_type`, `e`.`price_view`, `e`.`shipment_type`, `e`.`links_purchased_separately`, `e`.`links_exist`, `e`.`razmery`, `e`.`manufacturer_my`, `e`.`manufacturer_my_value`, `e`.`color_my`, `e`.`razmer_chashechki_2`, `e`.`obhvat_pod_grudyu_my`, `e`.`seasons`, `e`.`seasons_value`, `e`.`importance`, `e`.`importance_value`, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `eav_attribute_option`.`sort_order` FROM `catalog_product_flat_1` AS `e`
 INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id = '38'
 INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0
 LEFT JOIN `eav_attribute_option` ON eav_attribute_option.option_id = e.seasons
 LEFT JOIN `eav_attribute` ON eav_attribute.attribute_code = "seasons" AND eav_attribute.attribute_id = eav_attribute_option.attribute_id ORDER BY `eav_attribute_option`.`sort_order` ASC, `e`.`importance_value` DESC LIMIT 12

Откуда у меня ошибка вылазит? ((

Re: Сортировка по нескольким атрибутам

Может я могу в конце файла удалить как-то свои LEFT JOIN-ы ???

Re: Сортировка по нескольким атрибутам

Ну тут на вскидку ни чего сказать не могу. У меня таких проблем не было. Остатется только методом проб и ошибок :-).

Re: Сортировка по нескольким атрибутам

Ура, получилось )

 

В List.php добавил:

 

$this->_productCollection->getSelect()->joinLeft('eav_attribute_option', 'eav_attribute_option.option_id = e.seasons', array('eav_attribute_option.sort_order'));
$this->_productCollection->getSelect()->joinLeft('eav_attribute', join(' AND ', array('eav_attribute.attribute_code = "seasons"', 'eav_attribute.attribute_id = eav_attribute_option.attribute_id')), array());
$this->_productCollection->getSelect()->reset( Zend_Db_Select::ORDER );
$this->_productCollection->getSelect()->order(array('eav_attribute_option.sort_order ASC', 'e.importance_value DESC'));

А в шаблоне выключил указание количества товаров по фильтрам (фильтр в сайдбаре по цене и атрибутам - именно в запросе подсчета был конфликт)