Сортировка товаров по наличию

Правила раздела: faq.php?mode=okay
Модератор: Модераторы

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #1 makki » 20.03.2018, 09:52

Все замечания учтены. Работоспособность проверена

Предлагаю простое но полезное решение, которое переместит товары, которых нет на складе в конец списка.

В файле api/Products.php внутри функции get_produtcs находим такой фрагмент кода

Код: Выделить всё

if(!empty($filter['sort'])) {
            switch ($filter['sort']) {
                case 'rand':
                    $order = 'RAND()';
                    break;
                case 'position':
                    $order = 'p.position DESC';
                    break;
                case 'name':
                    $order = 'p.name ASC';
                    break;
                case 'name_desc':
                    $order = 'p.name DESC';
                    break;
                case 'rating':
                    $order = 'p.rating ASC';
                    break;
                case 'rating_desc':
                    $order = 'p.rating DESC';
                    break;
                case 'created':
                    $order = 'p.created DESC';
                    break;
                case 'price':
                    $order = "(SELECT -floor(IF(pv.currency_id=0 OR c.id is null,pv.price, pv.price*c.rate_to/c.rate_from)*$coef)
                        FROM __variants pv
                        LEFT JOIN __currencies c on c.id=pv.currency_id
                        WHERE
                            p.id = pv.product_id
                            AND pv.position=(SELECT MIN(position)
                                FROM __variants
                                WHERE
                                    product_id=p.id LIMIT 1
                            )
                        LIMIT 1) DESC";
                    break;
                case 'price_desc':
                    $order = "(SELECT -floor(IF(pv.currency_id=0 OR c.id is null,pv.price, pv.price*c.rate_to/c.rate_from)*$coef)
                        FROM __variants pv
                        LEFT JOIN __currencies c on c.id=pv.currency_id
                        WHERE
                            p.id = pv.product_id
                            AND pv.position=(SELECT MIN(position)
                                FROM __variants
                                WHERE
                                    product_id=p.id LIMIT 1
                            )
                        LIMIT 1) ASC";
                    break;
                case 'position':
                    $order = 'p.position DESC';
                    break;
            }
        }


После него вставляем следующее

Код: Выделить всё

       
        if(!empty($filter['sort'])){
            $order = 'IF(pv.stock < 1,1,0),'.$order;
            $variant_join = $this->db->placehold('LEFT JOIN (SELECT product_id,MAX(IFNULL(stock,?)) as stock FROM __variants GROUP BY product_id) pv ON p.id=pv.product_id', $this->settings->max_order_amount);
        }


Готово!
Последний раз редактировалось makki 21.03.2018, 07:02, всего редактировалось 4 раза.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #2 korshunov » 20.03.2018, 11:40

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

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

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

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #3 makki » 20.03.2018, 12:45

korshunov писал(а):Эта доработка, вообще говоря, функционирует неправильно. Реально работает так: у каждого товара случайным образом выбирается ОДИН ИЗ ВАРИАНТОВ, смотрится количество и проводится сортировка по этому количеству.
Поэтому, например, если у товара 5 вариантов, и только один из них с нулевым количеством, то товар вполне может оказаться внизу списка. А это совсем не целесообразно в такой ситуации.

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

В общем случае - совершенно непригоден, ИМХО...
Исправил. Теперь учитываются все варианты товара.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #4 korshunov » 20.03.2018, 13:26

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

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #5 makki » 20.03.2018, 14:03

korshunov писал(а):Видимо, этот вариант тоже не проверяли как следует.
Если у товара один вариант имеет кол-во 0, а другой - бесконечность, то товар опускается вниз, что неверно...
Исправил, теперь кажется все в порядке.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

siteapp M
siteapp M
Возраст: 32
Репутация: 7
Сообщения: 118
Зарегистрирован: 12.01.2016
С нами: 8 лет 2 месяца

Сообщение #6 siteapp » 18.05.2018, 15:18

makki писал(а):if(!empty($filter['sort'])){
            $order = 'IF(pv.stock < 1,1,0),'.$order;
            $variant_join = $this->db->placehold('LEFT JOIN (SELECT product_id,MAX(IFNULL(stock,?)) as stock FROM __variants GROUP BY product_id) pv ON p.id=pv.product_id', $this->settings->max_order_amount);
        }
как в версии 1.2.3 поставить?

Код: Выделить всё

 if(!empty($filter['sort'])) {
            switch ($filter['sort']) {
                case 'position':
                    $order = 'p.position DESC';
                    break;
                case 'name':
                    $order = 'p.name ASC';
                    break;
                case 'name_desc':
                    $order = 'p.name DESC';
                    break;
                case 'created':
                    $order = 'p.created DESC';
                    break;
                case 'price':
                    $order = "(SELECT -floor(IF(pv.currency_id=0 OR c.id is null,pv.price, pv.price*c.rate_to/c.rate_from)*$coef)
                        FROM __variants pv
                        LEFT JOIN s_currencies c on c.id=pv.currency_id
                        WHERE
                            p.id = pv.product_id
                            AND pv.position=(SELECT MIN(position)
                                FROM __variants
                                WHERE
                                    product_id=p.id LIMIT 1
                            )
                        LIMIT 1) DESC";
                    break;
                case 'price_desc':
                    $order = "(SELECT -floor(IF(pv.currency_id=0 OR c.id is null,pv.price, pv.price*c.rate_to/c.rate_from)*$coef)
                        FROM __variants pv
                        LEFT JOIN s_currencies c on c.id=pv.currency_id
                        WHERE
                            p.id = pv.product_id
                            AND pv.position=(SELECT MIN(position)
                                FROM __variants
                                WHERE
                                    product_id=p.id LIMIT 1
                            )
                        LIMIT 1) ASC";
                    break;
            }
        }

ставишь и сайт тупо грузится вечно, потом ошибка 404
:eh:

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #7 korshunov » 18.05.2018, 15:48

У меня работает на версии 1.2.3

siteapp M
siteapp M
Возраст: 32
Репутация: 7
Сообщения: 118
Зарегистрирован: 12.01.2016
С нами: 8 лет 2 месяца

Сообщение #8 siteapp » 18.05.2018, 15:58

korshunov писал(а):У меня работает на версии 1.2.3
скиньте плз файл
:eh:

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #9 korshunov » 19.05.2018, 05:23

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

Какой файл Вам скинуть и зачем? Чтоб Вы дали глуповатый ответ - а у меня не работает?

По моим наблюдениям, в 90% подобных случаев ошибка оказывается совсем не там, где неспециалисты ее упорно ищут.

Если дадите FTP, могу посмотреть Ваш случай...

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #10 makki » 19.05.2018, 20:01

Замечено, что с этим дополнением не работает фильтр по цене. Не стал разбираться как исправить, пока вместо

Код: Выделить всё

if(!empty($filter['sort'])){

написал

Код: Выделить всё

if(!empty($filter['sort']) && empty($filter['price'])){


Таким образом, если применяется фильтр по цене, сортировка по наличию отключается.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #11 korshunov » 20.05.2018, 06:34

Возможно, это связано с ошибкой разработчиков Okay:
viewtopic.php?f=7&t=859

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

siteapp M
siteapp M
Возраст: 32
Репутация: 7
Сообщения: 118
Зарегистрирован: 12.01.2016
С нами: 8 лет 2 месяца

Сообщение #12 siteapp » 21.05.2018, 19:39

korshunov писал(а):У меня работает на версии 1.2.3

У меня 40 000 товаров, когда вставляю этот код, то грузится страница 3 дня... А потом вылазит 404 ошибка
Проверил где в категории 110 страниц. Если сделать категорию и кинуть 10 товаров, то да, работает...
:eh:

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #13 korshunov » 22.05.2018, 06:15

Да, при большом к-ве товаров такое вполне может быть.
Похоже, способ makki в этой ситуации создает тяжелый запрос к БД.
Вообще и стандартные сортировки организованы далеко не оптимально, а тут к ним еще нагрузка добавляется...

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #14 makki » 23.01.2019, 11:36

Чтобы одновременно работала сортировка товаров по наличию и фильтр по цене, нужно в первом посте вместо

Код: Выделить всё

       
        if(!empty($filter['sort'])){
            $order = 'IF(pv.stock < 1,1,0),'.$order;
            $variant_join = $this->db->placehold('LEFT JOIN (SELECT product_id,MAX(IFNULL(stock,?)) as stock FROM __variants GROUP BY product_id) pv ON p.id=pv.product_id', $this->settings->max_order_amount);
        }

вставить

Код: Выделить всё

       
        if(!empty($filter['sort'])){
            $order = 'IF(pv.stock < 1,1,0),'.$order;
            $variant_join = $this->db->placehold('LEFT JOIN (SELECT product_id, currency_id, price, MAX(IFNULL(stock,?)) as stock FROM __variants GROUP BY product_id) pv ON p.id=pv.product_id', $this->settings->max_order_amount);
        }
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

korshunov
korshunov
Репутация: 146
Сообщения: 1854
Зарегистрирован: 03.12.2015
С нами: 8 лет 3 месяца
Skype

Сообщение #15 korshunov » 23.01.2019, 12:19

А зачем в последнем варианте извлекаются поля currency_id, price ? Вроде бы они совсем ни к чему...

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #16 makki » 23.01.2019, 12:21

korshunov писал(а):А зачем в последнем варианте извлекаются поля currency_id, price ? Вроде бы они совсем ни к чему...
они нужны для работы фильтра по цене.
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

siteapp M
siteapp M
Возраст: 32
Репутация: 7
Сообщения: 118
Зарегистрирован: 12.01.2016
С нами: 8 лет 2 месяца

Сообщение #17 siteapp » 24.01.2019, 08:10

makki писал(а):
korshunov писал(а):А зачем в последнем варианте извлекаются поля currency_id, price ? Вроде бы они совсем ни к чему...
они нужны для работы фильтра по цене.
При 40 000 не сломается теперь?)
:eh:

makki M
makki M
Репутация: 199
Сообщения: 697
Зарегистрирован: 12.08.2016
С нами: 7 лет 7 месяцев
Откуда: Киев
Сайт

Сообщение #18 makki » 24.01.2019, 08:49

siteapp писал(а):
makki писал(а):они нужны для работы фильтра по цене.
При 40 000 не сломается теперь?)
не знаю пробуйте.SQL запрос не упростился
Cоздание и расширение функционала интернет-магазина на платформе OkayCMS 2 (с 3-й и 4-й версией не работаю)

siteapp M
siteapp M
Возраст: 32
Репутация: 7
Сообщения: 118
Зарегистрирован: 12.01.2016
С нами: 8 лет 2 месяца

Сообщение #19 siteapp » 24.01.2019, 15:22

makki писал(а):
siteapp писал(а):При 40 000 не сломается теперь?)
не знаю пробуйте.SQL запрос не упростился
значит уплывёт)
:eh:

yodaexolon
yodaexolon
Репутация: 2
Сообщения: 14
Зарегистрирован: 12.01.2019
С нами: 5 лет 2 месяца

Сообщение #20 yodaexolon » 04.03.2019, 18:26

Если поставить эту доработку https://forum.okay-cms.com/viewtopic.php?f=10&t=643
то товары не отображаются на главной


Название раздела: Полезные решения для OkayCMS
Правила раздела: faq.php?mode=okay

Быстрый ответ


Введите код в точности так, как вы его видите. Регистр символов не имеет значения.
Код подтверждения

   

Вернуться в «Полезные решения для OkayCMS»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 15 гостей