Улучшение сортировки на витрине Opencart
Поступил вопрос:
можно ли сделать по умолчанию сортировку товаров на витрине, одновременно по двум параметрам: по цене и названию. Тоесть сортируются по цене, а те у кого цены одинаковые уже по имени. Я сделал по цене, но я заметил что иногда Опенкарт меняет местами товары с одинаковыми параметрами сортировки, например если менять кол-во выводимого товара на одну страницу, ощущение что их тусует в произвольном порядке.
Действительно, лучше это предусмотреть и заодно изменить стандартный способ сортировки по полю "sort_order" (которое мало кто использует в товарах) на сортировку по названию товара (а название у товара есть всегда), чтобы избежать популярной, но иногда незаметной ситуации, когда один и тот же товар может выводиться и на первой, и на второй странице (вообще-то на любых, если использовать стандартный способ сортировки, применяемый в Опенкарт).
Diff приведён ниже, здесь же приведу описание обычными словами, т.к изменение всего одно и небольшое:
Как внести изменения вручную
1. Открываем файл catalog/model/catalog/product.php
2. Ищем функцию function getProducts
3. Пролистываем почти до конца в поисках кода запроса с ORDER BY и следующего за ним LIMIT. Соответствующий участок кода выглядит так:
$sort_data = array( 'pd.name', 'p.model', 'p.quantity', 'p.price', 'rating', 'p.sort_order', 'p.date_added' ); if (isset($data['sort']) && in_array($data['sort'], $sort_data)) { if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') { $sql .= " ORDER BY LCASE(" . $data['sort'] . ")"; } else { $sql .= " ORDER BY " . $data['sort']; } } else { $sql .= " ORDER BY p.sort_order"; } if (isset($data['order']) && ($data['order'] == 'DESC')) { $sql .= " DESC"; } else { $sql .= " ASC"; } if (isset($data['start']) || isset($data['limit'])) { if ($data['start'] < 0) { $data['start'] = 0; } if ($data['limit'] < 1) { $data['limit'] = 20; } $sql .= " LIMIT " . (int)$data['start'] . "," . (int)$data['limit']; }
4. Мы сделаем две вещи: для начала изменим способ сортировки товаров на витрине по умолчанию на сортировку по названию:
} else { $sql .= " ORDER BY p.sort_order"; }
меняем на
} else { $sql .= " ORDER BY pd.name"; }
5. И теперь добавляем вторичную сортировку по названию:
if (isset($data['order']) && ($data['order'] == 'DESC')) { $sql .= " DESC"; } else { $sql .= " ASC"; } // БУДЕМ ВСТАВЛЯТЬ КОД СЮДА // БУДЕМ ВСТАВЛЯТЬ КОД СЮДА // БУДЕМ ВСТАВЛЯТЬ КОД СЮДА // БУДЕМ ВСТАВЛЯТЬ КОД СЮДА if (isset($data['start']) || isset($data['limit'])) {
Всталяем в указанное место такой блок кода:
// Additional sort order by product name if(isset($data['sort']) && $data['sort'] != 'pd.name') { $sql .= ", pd.name ASC"; }
Вот и всё.
То же самое в виде Diff-файла
commit c12debb0a37ade03e773535ed361a4b96bd54c91 Author: Ruslan Brest <rb@labtodo.com> Date: Mon May 21 10:26:39 2012 +0300 [+] Better catalog sort order: additional sorting by product name Добавлена вторичная сортировка по имени товара для более аккуратного вывода. Без этого товары при выборе других сортировок, например по количеству, могут сортироваться в случайном порядке. То же самое при изменении количества товаров на странице: один и тот же товар может оказаться и на первой, и на второй странице. Сейчас товары сортируются по выбранному признаку, а затем по имени. [!] CHANGED: По умолчанию -- сортировка по имени, а не по sort_order diff --git a/upload/catalog/model/catalog/product.php b/upload/catalog/model/catalog/product.php index 8b15e26..c3dec4f 100644 --- a/upload/catalog/model/catalog/product.php +++ b/upload/catalog/model/catalog/product.php @@ -162,7 +162,7 @@ class ModelCatalogProduct extends Model { $sql .= " ORDER BY " . $data['sort']; } } else { - $sql .= " ORDER BY p.sort_order"; + $sql .= " ORDER BY pd.name"; } if (isset($data['order']) && ($data['order'] == 'DESC')) { @@ -171,6 +171,11 @@ class ModelCatalogProduct extends Model { $sql .= " ASC"; } + // Additional sort order by product name + if(isset($data['sort']) && $data['sort'] != 'pd.name') { + $sql .= ", pd.name ASC"; + } + if (isset($data['start']) || isset($data['limit'])) { if ($data['start'] < 0) { $data['start'] = 0;