Jump to content

Сортировка товаров, товар c кол-вом 0 в конец списка + сорт. по цене


Recommended Posts

Код исправлен, работоспособен и проверен!! Все замечания высказанные kors учтены!

 

Решение простое:

открываем файл: api/Products.php

 

находим функцию: public function get_products($filter = array())

 

Находим кусок кода:

 		if(!empty($filter['sort']))
			switch ($filter['sort'])
			{
				case 'position':
				$order = 'p.position DESC';
				break;
				case 'name':
				$order = 'p.name';
				break;
				case 'created':
				$order = 'p.created DESC';
				break;
				case 'price-min':
				$order = 'v.price';
				break;
				case 'price-max':
				$order = 'v.price DESC';
				break;
			} 

После этого кода вставляем:

/**/	if(!empty($filter['sort'])){
/**/		$order = 'IF(v.stock < 1,1,0),'.$order;
/**/		$group_by = 'GROUP BY p.id';
/**/		$products_stock_null_sort = 'INNER JOIN __variants v ON p.id = v.product_id';
/**/	} 

После находим запрос:

$query = "SELECT  
					p.id,
					p.url,
					p.brand_id,
					p.name,
					p.annotation,
					p.body,
					p.position,
					p.created as created,
					p.visible, 
					p.featured,
					p.rating,
					p.votes, 
					p.meta_title, 
					p.meta_keywords, 
					p.meta_description, 
					b.name as brand,
					b.url as brand_url
............

в этом запросе находим: LEFT JOIN __brands b ON p.brand_id = b.id

после этой строки вставляем: $products_stock_null_sort

Так, чтобы получилось:

				LEFT JOIN __brands b ON p.brand_id = b.id
				$products_stock_null_sort 

+

Под эту же фишку легко сделать СОРТИРОВКУ  ТОВАРА ПО ЦЕНЕ, от меньшей к большему и наоборот, для этого в этом же файле: api/Products.php

в этой же функции:public function get_products($filter = array())

находим:

 		if(!empty($filter['sort']))
			switch ($filter['sort'])
			{
				case 'position':
				$order = 'p.position DESC';
				break;
				case 'name':
				$order = 'p.name';
				break;
				case 'created':
				$order = 'p.created DESC';
				break;
			} 

и заменяем на:

 		if(!empty($filter['sort']))
			switch ($filter['sort'])
			{
				case 'position':
				$order = 'p.position DESC';
				break;
				case 'name':
				$order = 'p.name';
				break;
				case 'created':
				$order = 'p.created DESC';
				break;
				case 'price-min':
				$order = 'v.price';
				break;
				case 'price-max':
				$order = 'v.price DESC';
				break;
			} 

 

Как видим добавили две сортировки: 

price-min - от меньшей цены к большей

price-max - от большей цены к меньшей

 

Для проверки у себя в каталоге товара в URL вставляем: ?sort=price-min

Получится примерно так: http://domen.zz/catalog/nevidimka/?sort=price-min

 

 

Пробуйте!

Благодарности в комментарии....

Edited by cernos
Link to post
Share on other sites

1. Указанное в заголовке "товар c кол-вом 0", строго говоря, бессмыслица, так как в Simpla у товаров количества НЕТ, оно есть у вариантов.

 

2. Предлагаемый прием портит стандартную сортировку списка товаров в админке. Для админов, часто работающих со списком, может оказаться малоприятным сюрпризом, что все товары исчезли с привычных мест и перемешались. Более того, с течением времени они самопроизвольно будут перемещаться в списке и в дальнейшем.

 

3. Если в запрос добавлено INNER JOIN __variants v ON p.id = v.product_id, то надо позаботиться о группировке по товарам. Иначе в запросе появляется НЕСКОЛЬКО строк с одним товаром (этого не будет на странице категории, но будет на странице результатов поиска). Хотя они при последующей обработке во view перезаписываются друг на друга, и в последующем один товар представлен одной записью, все равно имеем нерациональность.

 

4. Сам метод очень сомнителен, так как при сортировке учитывает цену ТОЛЬКО ОДНОГО ВАРИАНТА, и не подозревает о том, что у товара можете быть несколько вариантов, часть из которых с количеством 0, а часть - с количеством больше 0.

 

5. Метод работает правильно только в том случае, когда у всех товаров только по одному варианту. В общем же случае получаемый в результате порядок товаров довольно случаен.

Link to post
Share on other sites

.

 

4. Сам метод очень сомнителен, так как при сортировке учитывает цену ТОЛЬКО ОДНОГО ВАРИАНТА, и не подозревает о том, что у товара можете быть несколько вариантов, часть из которых с количеством 0, а часть - с количеством больше 0.

 

5. Метод работает правильно только в том случае, когда у всех товаров только по одному варианту. В общем же случае получаемый в результате порядок товаров довольно случаен.

Проверил на нескольких вариантах. В одном варианте кол-во стоит 0, в другом же стоит 5. Товар выводится в той очередности в которой и ранее выводился. Ставлю оба варианта в 0, товар улетает в конец списка.

 

 

1. Указанное в заголовке "товар c кол-вом 0", строго говоря, бессмыслица, так как в Simpla у товаров количества НЕТ, оно есть у вариантов.

 

2. Предлагаемый прием портит стандартную сортировку списка товаров в админке. Для админов, часто работающих со списком, может оказаться малоприятным сюрпризом, что все товары исчезли с привычных мест и перемешались. Более того, с течением времени они самопроизвольно будут перемещаться в списке и в дальнейшем.

Лично меня смущает больше другое, когда среди товара на первой странице категории есть товар с надписью "нет в наличии", не на одном хорошем магазине этого я не замечал, да и зачем покупателю выдавать информацию о товаре, которого нет в наличии, по крайней мере в самом начале списка?

 

 

.

3. Если в запрос добавлено INNER JOIN __variants v ON p.id = v.product_id, то надо позаботиться о группировке по товарам. Иначе в запросе появляется НЕСКОЛЬКО строк с одним товаром (этого не будет на странице категории, но будет на странице результатов поиска). Хотя они при последующей обработке во view перезаписываются друг на друга, и в последующем один товар представлен одной записью, все равно имеем нерациональность.

 

 

Привожу пример выборки из тестовой БД simpla в phpmyadmin:

Вариант стандартный

Запрос:

SELECT p.id, p.url, p.brand_id, p.name, p.annotation, p.body, p.position, p.created as created, p.visible, p.featured, p.rating, p.votes, p.meta_title, p.meta_keywords, p.meta_description, b.name as brand, b.url as brand_url FROM s_products p INNER JOIN s_products_categories pc ON pc.product_id = p.id AND pc.category_id in('3') LEFT JOIN s_brands b ON p.brand_id = b.id  WHERE 1 AND p.visible=1 GROUP BY p.id, p.position DESC LIMIT 0, 24

Результат на скриншоте http://s019.radikal.ru/i632/1409/ad/3712b97cddf9.jpg

 

Вариант моего запроса:

Запрос: 

SELECT p.id, p.url, p.brand_id, p.name, p.annotation, p.body, p.position, p.created as created, p.visible, p.featured, p.rating, p.votes, p.meta_title, p.meta_keywords, p.meta_description, b.name as brand, b.url as brand_url FROM s_products p    INNER JOIN s_products_categories pc ON pc.product_id = p.id AND pc.category_id in('3') LEFT JOIN s_brands b ON p.brand_id = b.id INNER JOIN s_variants v ON p.id = v.product_id WHERE 1 AND p.visible=1 GROUP BY p.id ORDER BY IF(v.stock < 1,1,0), p.position DESC LIMIT 0, 24 

Результат на скриншоте http://s001.radikal.ru/i194/1409/d1/c818143d9ec2.jpg

 

 

Скриншот данных таблицы конкретно variants: 

http://s009.radikal.ru/i309/1409/1c/7fb02d44acba.jpg

 

А теперь объясните мне, в чем разница?

Результат выдачи двух запросов одинаков, для сверки количества вариантов смотрите скрин таблицы вариантов, там есть два товара, у которых один вариант с количеством 0, а другой вариант с кол-во 2 и 5.

 

Я могу предположить свою неправоту, но не в данном случае...

Что касается INNER и LEFT JOIN читайте документацию, определите в чем есть разница!!!

 

ПОТЕСТИРУЙТЕ У СЕБЯ - КИНЬТЕ В МЕНЯ БАНАНОМ, если что не так!

Link to post
Share on other sites

По пп. 4,5, я, похоже, поспешил с выводами, в этом плане вроде бы все нормально.

А поводу остальных - все замечания остаются в силе.

 

Что касается п.2, то, как оказалось, в админке все обстоит значительно хуже - не только порядок меняется, но и товары пропадают.

 

6. На стандартной Simpla 2.3.6 устанавливаю описанные Вами изменения.

После этого открываю в админке страницу товаров. Обычно на стандартной установке есть три страницы товаров с длиной списка 20 + 20 + 2 пунктов. После Ваших изменений имеем 3 страницы с количеством 12 + 20 + 10. Но это еще беда небольшая. А вот если в настройках установить "Товаров на странице админки" 21 вместо стандартных 20, то получится две страницы товаров с длиной списка 13 + 21 пунктов, то есть меньше, чем должно быть. Если открыть "все сразу", то в заголовке пишет 42 товара, а в списке только 34. В итоге получаем страшный кошмар для админа - ни с того ни с сего 8 товаров пропали. С точки зрения админа предлагаемая доработка - просто диверсия...

 

7. Для стандартной начальной установки Simpla при экспорте имеем в файле 55 строк. После установки предлагаемой доработки в файле экспорта 54 строки. При беглом взгляде видно, что в списке только 1 (!) товар из категории Фотоаппараты, а должно быть больше. Предлагаемый способ - ох какой большой риск для админа...

 

Уважаемый Kosjak76 на этом форуме не раз советовал без серьезной надобности не трогать API. Признаться, я к этим его советам раньше относился скептически. А сейчас уже начинаю думать, что он, пожалуй, прав...

Link to post
Share on other sites

Kors, по поводу админки - упустил из виду что и админка использует этот же API. Вот за это спасибо! Как исправлю и выложу изменения!

Link to post
Share on other sites

По пп. 4,5, я, похоже, поспешил с выводами, в этом плане вроде бы все нормально.

А поводу остальных - все замечания остаются в силе.

 

Что касается п.2, то, как оказалось, в админке все обстоит значительно хуже - не только порядок меняется, но и товары пропадают.

 

6. На стандартной Simpla 2.3.6 устанавливаю описанные Вами изменения.

После этого открываю в админке страницу товаров. Обычно на стандартной установке есть три страницы товаров с длиной списка 20 + 20 + 2 пунктов. После Ваших изменений имеем 3 страницы с количеством 12 + 20 + 10. Но это еще беда небольшая. А вот если в настройках установить "Товаров на странице админки" 21 вместо стандартных 20, то получится две страницы товаров с длиной списка 13 + 21 пунктов, то есть меньше, чем должно быть. Если открыть "все сразу", то в заголовке пишет 42 товара, а в списке только 34. В итоге получаем страшный кошмар для админа - ни с того ни с сего 8 товаров пропали. С точки зрения админа предлагаемая доработка - просто диверсия...

 

7. Для стандартной начальной установки Simpla при экспорте имеем в файле 55 строк. После установки предлагаемой доработки в файле экспорта 54 строки. При беглом взгляде видно, что в списке только 1 (!) товар из категории Фотоаппараты, а должно быть больше. Предлагаемый способ - ох какой большой риск для админа...

 

Уважаемый Kosjak76 на этом форуме не раз советовал без серьезной надобности не трогать API. Признаться, я к этим его советам раньше относился скептически. А сейчас уже начинаю думать, что он, пожалуй, прав...

Как выяснилось, товары в админке не пропадали, из-за того что в базовом запросе я не делал GROUP BY p.id в результате запроса возникало несколько записей с одинаковым p.id, но с разными вариантами товара. При выдаче на сайте результат с одинаковым p.id сливалсяв одну запись, из-за этого, вместо требуемых 20 товаров мы получали кол-во меньшее. Но в результате недостающий товар показывался ниже в других страницах. После группировки все исправилось.

 

Так же решил проблему с опусканием товара с количеством "0" в админке. Для админки сортировка отключается, работает только на самом сайте. Все проверено было как в админке, так и на самом сайте!

 

Новая инструкция выложена в стартовый топик!

Link to post
Share on other sites

Спасибо, в новом виде, похоже, работает, как следует.

 

Маленькое замечание по способу реализации. Сейчас для включения особой сортировки используется условие if(!empty($filter['sort'])).

Условие несколько искусственно и способ выбивается в сторону от весьма прозрачной и удобной системной идеологии Simpla. Например, если кто-то решит добавить сортировку в новое место, где ее до сих пор не было (скажем, в экспорте), но не получит желаемого эффекта.

 

ИМХО, идейно правильнее было бы ввести новый параметр типа $filter['sort_stock_0_to_end'] и использовать его.

Link to post
Share on other sites

Kors в принципе вывести условие в отдельный фильтр несложно, но для инициализации этого условия, придется править еще и файл view/ProductsView.php

 

Будет запрос на реализацию, сделаю.

Link to post
Share on other sites

Конечно, придется чуть больше поработать. Зато новый функционал будет работать ТОЛЬКО там, где это будет явно указано во view, и у Вас с гарантией не будет "сюрпризов" типа "упустил из виду что и админка использует этот же API". И не надо перекапывать всю систему и проверять все вызовы функции get_products, чтобы убедиться в отсутствии конфликтов...

Link to post
Share on other sites
  • 2 months later...

Прищлось править данное решение на одном сайте.

Проблема была в следующем - проверка по наличию идет только по первому варианту.

Я сделал так:

/**/	if(!empty($filter['sort'])){
/**/       $order = 'IF((SELECT COUNT(*) FROM __variants WHERE (stock>0 OR stock IS NULL) AND product_id=p.id LIMIT 1), 1, 0) DESC,'.$order; 
/**/	}

Работает при любой сортировке и сбрасывает вниз товары, у которых нет ни одного варианта.

Link to post
Share on other sites

Насколько я понимаю, это и в админке поменяет стандартную сортировку в товарах. А это далеко не каждому админу понравится...

Link to post
Share on other sites
  • 1 month later...

по другому сделал в api/Products.php

добавил в запрос сразу задание сортировки через доп. запрос:
 

                case 'position':
                $order = '(SELECT IF(pv.stock>0,1,0) FROM __variants pv WHERE p.id = pv.product_id LIMIT 1) DESC, p.position ASC';
                //$order = 'p.position ASC';
                break;

 

 

админку это не портит

Edited by Ergo
Link to post
Share on other sites
  • 2 months later...

поиск отваливается после добавления этой сортировки, проверьте кто ставил у себя поиск, или все работает

нужно анализировать, почему он отвалился : ) Не должен отваливаться!

Link to post
Share on other sites
  • 8 months later...

Версия 2.2.3. Сортировка по цене не работает, сортирует также как и по умолчанию, но товар с нулевым остатком теперь в конце, что уже хорошо) Поиск работает.

Link to post
Share on other sites

Подскажите как вставить в шаблон сортировку вверх, вниз на примере:

 

<option value="{url sort=price page=null}"{if $sort=='price'} selected{/if}>цене</option>
 

Просто при замене на price-max не работает, выводит ссылку на ?sort=0

Edited by Julius123
Link to post
Share on other sites
  • 3 months later...

Оказывается, эта доработка сортирует  совсем неправильно. Реально работает примерно так: у каждого товара случайным образом выбирается ОДИН ИЗ ВАРИАНТОВ, смотрится количество и  проводится сортировка по этому количеству.

 

Если у всех товаров имеется лишь по одному варианту, то этот метод работает правильно.

 

В общем случае - совершенно непригоден...

Link to post
Share on other sites
×
×
  • Create New...