Jump to content

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


Recommended Posts

Строку надо добавить в api/Products.php

 

   $products_stock_null_sort='';

   /**/ 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';

   /**/ }

 

Спасибо Kors 

 

но доработка действительно фильтрует криво.

 

Допустим есть два цвета товара черный и белый, если черный в наличии, а белый нет, то этот товар попадет под фильтр и будет внизу с другими товарами которых нет в наличии....

Edited by snagovskiy
Link to post
Share on other sites
  • Replies 53
  • Created
  • Last Reply

Top Posters In This Topic

 

Строку надо добавить в api/Products.php
 
   $products_stock_null_sort='';
   /**/ 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';
   /**/ }
 
Спасибо Kors 
 
но доработка действительно фильтрует криво.
 
Допустим есть два цвета товара черный и белый, если черный в наличии, а белый нет, то этот товар попадет под фильтр и будет внизу с другими товарами которых нет в наличии....

 

вариант Кости пробовали? у меня он работает отлично

Link to post
Share on other sites

Пробовал, не помогло. Я купил http://simpla-tuning.com/spisok-tovarov---otsutstvuyuschie-v-kontse работает отлично

А если вдруг поставите доработку своя валюта на вариант. Где будут цены закупки  то $. то в рублях, то в евро. Как будет работать сортировка? Таки я вам скажу - будет жопа

Edited by Varyag
Link to post
Share on other sites

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

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

Я сделал так:

/**/	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

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

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

Я сделал так:

/**/	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; 
/**/	}

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

 

Несколько усложнено.  Чуть проще:

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

А если вдруг поставите доработку своя валюта на вариант. Где будут цены закупки  то $. то в рублях, то в евро. Как будет работать сортировка?

 

1. Обычно на форуме выкладывается решение, рассчитанное на стандартную Simpla.  Случай, когда  "А если вдруг поставите..." при этом не рассматривается. Вы ведь при покупке холодильника не обсуждаете вопрос - а что будет, если я переделаю в доме розетки, их станет меньше и мне некуда будет вилку вставить. Или наводнение случится...

2. Реально ответ на Ваш вопрос зависит от того, как выполнялась доработка. Мне приходилось делать разные подобные доработки. При правильном подходе все работает нормально:

http://simpla-tuning.com/search?keyword=%D1%86%D0%B5%D0%BD+%D0%B2%D0%B0%D0%BB%D1%8E%D1%82

 

Неправильный подход можно найти в теме:

http://forum.simplacms.ru/topic/8602-%D0%B2%D0%B2%D0%BE%D0%B4-%D1%86%D0%B5%D0%BD-%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82%D0%BE%D0%B2-%D0%B2-%D0%BB%D1%8E%D0%B1%D0%BE%D0%B9-%D1%83%D0%B4%D0%BE%D0%B1%D0%BD%D0%BE%D0%B9-%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B5%D0%BF%D0%BE%D1%81%D1%82%D0%B0/

Там автор в процессе создал даже несколько версий, но полностью все ошибки до конца так и не исправил

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

Код исправлен, работоспособен и проверен!! Все замечания высказанные 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

 

 

Пробуйте!

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

 

Прикрутил все как по инструкции, но как только обновил страницу с товарами, товары пропали. Как только убираю код из api/Products.php тогда сразу все норм становится... какие-то проблемы или что я не совсем понимаю может кто-то готов помочь? 

Link to post
Share on other sites

Я сделал немного по другому... в API в функции get_products переделал условие:

if(!empty($filter['in_stock']))
	$in_stock_filter = $this->db->placehold('AND (SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) = ?', intval($filter['in_stock']));
else
	$order_stock = '(SELECT 1 FROM __variants pv WHERE pv.product_id=p.id AND pv.price>0 AND (pv.stock IS NULL OR pv.stock>0) LIMIT 1) DESC, ';

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

SELECT ...
FROM ...
WHERE ...
ORDER BY $order_stock $order

Все, теперь сортировка работает только тогда, когда запрашиваешь ВСЕ товары, не обращая на то, есть ли они в наличии.

Если у товара есть вариант, возвращает 1, если нет, не возвращает ничего :) А сортировка идет в обратном порядке, то есть сначала те, что в наличии и потом отсутствующие! 

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

:) а как сделать чтоб товары которые количество 0 , были в конце в админ панели?

 

Без недостатков, скорее всего, никак. Потому что в админ-панели, кроме прочего, задается  сортировка именно по порядку товаров.

Можно формально менять сортировку именно в админке, но тогда возможны проблемы. Например исходная сортировка может сбиваться (при сохранении списка).

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

Link to post
Share on other sites

Без недостатков, скорее всего, никак. Потому что в админ-панели, кроме прочего, задается  сортировка именно по порядку товаров.

Можно формально менять сортировку именно в админке, но тогда возможны проблемы. Например исходная сортировка может сбиваться (при сохранении списка).

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

 

Ну а данный метод не затрагивает сейчас админ панель? 

Link to post
Share on other sites

Затрагивает одновременно и админку и витрину. При этом методе в админке отсутствующие находятся в конце.

И это один из недостатков предложенного метода - он, вообще говоря, не позволяет в админке правильно задавать желаемую сортировку и более того, может эту сортировку самопроизвольно менять. Ибо изначально подход к решению вопроса у автора принципиально неверный...

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

А это для какой версии? 

 

	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 'pricemin':
				//$order = 'pv.price IS NULL, pv.price=0, pv.price';
				$order = '(SELECT -pv.price FROM __variants pv WHERE (pv.stock IS NULL OR pv.stock>0) AND p.id = pv.product_id AND pv.position=(SELECT MIN(position) FROM __variants WHERE (stock>0 OR stock IS NULL) AND product_id=p.id LIMIT 1) LIMIT 1) DESC';
				break;
				case 'pricemax':
				$order = '(SELECT -pv.price FROM __variants pv WHERE (pv.stock IS NULL OR pv.stock>0) AND p.id = pv.product_id AND pv.position=(SELECT MIN(position) FROM __variants WHERE (stock>0 OR stock IS NULL) AND product_id=p.id LIMIT 1) LIMIT 1)';
				break;
			}
Link to post
Share on other sites
  • 3 months later...

Код исправлен, работоспособен и проверен!! Все замечания высказанные 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

 

 

Пробуйте!

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

Спасибо!!!!

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

Все сделал по инструкции, но перестал после этого работать поиск, то есть по запросу товары не находит, только возвращаю назад, так товар в поиске снова ищется. Как можно это исправить, буду признателен?))

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

А как сделать в карточке товара (у меня варианты (размеры) выводятся через select), чтобы при количестве варианта 0 - выводилось вконец списка? типа так:

размеры:

  • 38
  • 39
  • 40
  • 35
  • 36
  • 41 

мой код:

				
					{foreach $product->variants as $v}
						{if $v->stock == 0}
							<option {if $v->stock == 0}disabled{/if} data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{else}
							<option data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}

 

Link to post
Share on other sites
1 час назад, get31 сказал:

А как сделать в карточке товара (у меня варианты (размеры) выводятся через select), чтобы при количестве варианта 0 - выводилось вконец списка? типа так:

размеры:

  • 38
  • 39
  • 40
  • 35
  • 36
  • 41 

мой код:


				
					{foreach $product->variants as $v}
						{if $v->stock == 0}
							<option {if $v->stock == 0}disabled{/if} data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{else}
							<option data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}

 

https://www.php.net/manual/ru/function.usort.php

Link to post
Share on other sites

Самое простое

					{foreach $product->variants as $v}
						{if $v->stock > 0}
							<option data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}
					{foreach $product->variants as $v}
						{if $v->stock == 0}
							<option {if $v->stock == 0}disabled{/if} data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}

 

Link to post
Share on other sites
В 25.08.2021 в 20:38, phukortsin сказал:

Самое простое


					{foreach $product->variants as $v}
						{if $v->stock > 0}
							<option data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}
					{foreach $product->variants as $v}
						{if $v->stock == 0}
							<option {if $v->stock == 0}disabled{/if} data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}

 

Спасибо, чет об этом варианте не подумал))

Link to post
Share on other sites
  • 2 weeks later...
В 25.08.2021 в 20:38, phukortsin сказал:

Самое простое


					{foreach $product->variants as $v}
						{if $v->stock > 0}
							<option data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}
					{foreach $product->variants as $v}
						{if $v->stock == 0}
							<option {if $v->stock == 0}disabled{/if} data-name="{$product->name}" id="product_{$v->id}" name="variant" value="{$v->id}" data-price="{$v->price|convert} {$currency->sign|escape}" data-compare-price="{$v->compare_price|convert} {$currency->sign|escape}">{$v->size}</option>
						{/if}
					{/foreach}

 

Подскажите, пожалуйста, если в каком-то из вариантов цена на товар стоит выше или ниже, как вывести в селекте внизу типа "Цены могут отличаться, если товар..."

Сейчас вывожу таким образом, работает на всё где цены разные и одни:

{if $product->variant->price < $v->price || $product->variant->price > $v->price}
<optgroup>
<option>Цены могут отличаться, если товар...</option>
</optgroup>
{/if}

Через {if $v@first} не пройдет т.к вариант может быть ниже

Link to post
Share on other sites
1 час назад, get31 сказал:

Подскажите, пожалуйста, если в каком-то из вариантов цена на товар стоит выше или ниже, как вывести в селекте внизу типа "Цены могут отличаться, если товар..."

Сейчас вывожу таким образом, работает на всё где цены разные и одни:



{if $product->variant->price < $v->price || $product->variant->price > $v->price}
<optgroup>
<option>Цены могут отличаться, если товар...</option>
</optgroup>
{/if}

Через {if $v@first} не пройдет т.к вариант может быть ниже

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

Link to post
Share on other sites
14 минут назад, ps-simpla сказал:

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

есть размеры с ценами:

  • 36 - 100$
  • 37 - 100$
  • 38 - 150$
  • 39 - 100$

38 размер дороже, вот и интересует как вывести "Цены могут отличаться, если товар..." если 38 дороже

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...