Продолжаем модифицировать купленный нами за очень дорого магазин Симпла (http://simp.la). На сей раз добавим столько необходимый для магазина функционал, как сортировка товаров по цене и названию в обе стороны (по возрастанию и убыванию). Можно еще добавить в этот список сортировку по дате поступления, но поскольку это в большинстве случаев не публикуемые данные, то ограничимся наиболее популярным набором. Итак, поехали…
Те, у кого не было правок в классе Storefront (да и просто для примера вставки кода) могут скачать базовый класс Storefront с сортировкой. Далее же будет расписано что и как сделано по правкам.
Первым шагом стоит сделать выбор этой самой сортировки. Можно сделать либо списком, либо ссылками, что лично мне больше нравится, т.к. визуально понятнее.

<div class="order_by">
Сортировать по цене
<a href="{if $category}catalog/{$category->url}/{elseif $brand}brands/{/if}{if $brand}{$brand->url}/{/if}{if $filter_params}{$filter_params}&{else}?{/if}order=price">возр</a> |
<a href="{if $category}catalog/{$category->url}/{elseif $brand}brands/{/if}{if $brand}{$brand->url}/{/if}{if $filter_params}{$filter_params}&{else}?{/if}order=price_desc">убыв</a>,
по названию
<a href="{if $category}catalog/{$category->url}/{elseif $brand}brands/{/if}{if $brand}{$brand->url}/{/if}{if $filter_params}{$filter_params}&{else}?{/if}order=name">возр</a> |
<a href="{if $category}catalog/{$category->url}/{elseif $brand}brands/{/if}{if $brand}{$brand->url}/{/if}{if $filter_params}{$filter_params}&{else}?{/if}order=name_desc">убыв</a></div>

Теперь нам надо обработать входные параметры запроса на наличие признака сортировки и выполнить саму сортировку.
Открываем файл Storefront.class.php в корне сайта. Вознокла необходимость вынести отправку данных по фильтрам $this->smarty->assign(‘filter_params’, $this->form_get(array())); за пределы проверки свойств товара, а именно находим условие (примерно 144 строка).

if($properties = $this->db->results()) { 
... 
}

И в конце условия удаляем строку отправки данных. Вместо нее за пределами условия добавляем нашу расширенную конструкцию:

        $extra_params = array();
        if($this->add_param('order')) $extra_params['order'] = $this->param('order');
        $this->smarty->assign('filter_params', $this->form_get($extra_params));

Дело в том, что разработчик предусмотрел возможности передачи дополнительных параметров в метод form_get, поэтому мы без проблем передадим данные по сортировки. Передача filter_params надо, например, для постраничной навигации. Правильнее было бы формировать для каждого типа фильтра свой URL через метод form_get ,т.к. возможно дублирование параметров с разными значениями, но это усложнит задачу из-за количества переменных, а на работу все-равно не повлияет — поэтому работаем по упрощенной схеме.
далее находим вызов списка товаров $this->get_products — по идее сразу после нашего нового кода параметров. И в конец вызова добавляем null, $this->param(‘order’), т.е. null — это значения для параметра hit и далее мы передаем еще 1 параметр в метод получения списка товаров с указанием типа сортировки. Должно получиться

        $products = $this->get_products(null, (array)$category->category_id, isset($brand->brand_id)?$brand->brand_id:null, $start_item, $filter, NULL, $this->param('order'));

Теперь правим сам метод get_products. Находим function get_products в районе 475 строки и заменяем объявление функции на

    function get_products($ids = null, $categories = null, $brand_id = null, $start_item=null, $filter=null, $hit=null, $order = false)

Т.е. мы тут получили наш параметр order и по-умолчанию присвоили ему false.
Теперь обработаем входные данные по сортировке и допишем наш запрос к базе. После объявления переменной $hit_filter добавим наш блок обработки

    // Выбираем сортировку
        if($order)
            switch ($order) {
                case 'name_desc': 
                    $order_filter = "products.model DESC";
                    $variant = "";
                    break;
                case 'price': 
                    $order_filter = "products_variants.price";
                    $variant = " LEFT JOIN products_variants ON products_variants.product_id = products.product_id";
                    break;
                case 'price_desc': 
                    $order_filter = "products_variants.price DESC";
                    $variant = " LEFT JOIN products_variants ON products_variants.product_id = products.product_id";
                    break;
                default:
                    $order_filter = is_null($hit) ? "products.model" : "rand(), products.model";
                    $variant = "";
            }
            else {
                $order_filter = is_null($hit) ? "products.model" : "rand(), products.model";
                $variant = "";
            }

Тут мы добавили 2 переменных:

  • $order_filter — непосредственна сама сортировка
  • $variant — по-умолчанию таблица вариантов у нас не подключена (а именно в ней хранятся цены), мы тоже будет ее подключать по мере необходимости. Это усложнит немного логику, но сэкономит процессорное время и следовательно и скорость загрузки страницы

Вот и добрались до самого интересного — самого запроса к базе товаров… Заменяем запрос после объявления переменной $category_filter на наш

$query = "SELECT  
                products.product_id, products.url, products.category_id, products.brand_id, products.tara, products.model, products.description, products.body, products.hit, products.order_num, products.small_image, products.large_image, DATE_FORMAT(products.created, '%Y-%m-%d') as created, DATE_FORMAT(products.modified, '%Y-%m-%d') as  modified, products.enabled, 
                brands.name as brand, brands.url as brand_url,
                categories.single_name as category, categories.url as category_url, categories.image as category_image
                FROM products LEFT JOIN categories ON categories.category_id = products.category_id
                LEFT JOIN brands ON products.brand_id = brands.brand_id
                LEFT JOIN products_categories ON products.product_id = products_categories.product_id $variant
                WHERE 
                categories.enabled=1
                and products.enabled=1                     
                $id_filter $category_filter $brand_filter $properties_filter $hit_filter 
                GROUP BY products.product_id 
                ORDER BY $order_filter $limit";

Вот и вся практическая магия.
Всегда рад помочь, особенно, если это вознаграждается 🙂 Всем удачи!

Опубликовать в Яндекс
Опубликовать в Facebook
Опубликовать в Мой Мир
Опубликовать в Одноклассники
Опубликовать в LiveJournal
Опубликовать в Google Plus
Опубликовать в Google Buzz