Opencart. Товары с ценой “0” в конце списка + BrainyFilter

Opencart. Товары с ценой “0” в конце списка + BrainyFilter – цена 0 рублей (или нулевая цена любой другой валюты) для товара в магазине на базе Opencart (OcStore) может использоваться с разной целью. Например, цена на товар меняется очень быстро и в некоторых случаях 0 в цене меняют на фразу “По запросу”. А иногда нулевую цену используют как условия для запрета покупки данной вещи, оставляя при этом товар в каталоге для расширения ассортимента и улучшения по SEO. Примеров можно привести достаточно много и каждый использует нулевую цену по-разному.

Однако, товар с ценой “0” в каталоге при сортировке цен “по возрастанию” занимает первые места каталога, а иногда и вовсе портит картину сайта перемешиваясь с остальным товаром, сбивая с толку и нередко раздражая посетителей Вашего сайта. Исправить это можно достаточно быстро.

Изменения вносятся только в 1 файл, а именно в модель продукта, которая находится в директории:

catalog/model/catalog/product.php

В OcStore 2.1 примерно строка 160 метод getProducts(), OcStore 2.3 примерно строка 169 метод getProducts()

Находим фрагмент кода:

		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'] . ")";
			} elseif ($data['sort'] == 'p.price') {
				$sql .= " ORDER BY (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
			} else {
				$sql .= " ORDER BY " . $data['sort'];
			}
		} else {
			$sql .= " ORDER BY p.sort_order";
		}

и меняем его на следующий фрагмент:

		if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
			if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), LCASE(" . $data['sort'] . ")";
			} elseif ($data['sort'] == 'p.price') {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
			} else {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), " . $data['sort'];
			}
		} else {
			$sql .= " ORDER BY IF(p.price = '0', 1, 0), p.sort_order";
		}

Сохраняем, обновляем файл на Вашем сайте. Не забываем обновлять кеш модификаторов! Готово!
Так же можно создать модификатор, не меняя файл product.php напрямую, выглядит он следующим образом:

<?xml version="1.0" encoding="utf-8"?>
<modification>
  <name>Товар с 0 ценой в конец списка</name>
  <code>last_price_null</code>
  <version>1</version>
  <author>valdemariuses</author>
  <link>https://nikonorow.ru/</link>
  <file path="catalog/model/catalog/product.php">
    <operation>
      <search index="0"><![CDATA[if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {]]></search>
      <add position="replace" offset="10"><![CDATA[		if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
			if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), LCASE(" . $data['sort'] . ")";
			} elseif ($data['sort'] == 'p.price') {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
			} else {
				$sql .= " ORDER BY IF(p.price = '0', 1, 0), " . $data['sort'];
			}
		} else {
			$sql .= " ORDER BY IF(p.price = '0', 1, 0), p.sort_order";
		}]]></add>
    </operation>
  </file>
</modification>

Данный способ я обнаружил на сайте oc-new.com и благодарю автора под ником valdemariuses за решение проблемы.

Но что делать, если у Вас установлен Brainy Filter или как его еще называют – умный фильтр?

Через стандартную модель product.php и способ сортировки товаров, описанный выше, сделать не получится, поскольку у плагина умного фильтра своя сортировка и она перезаписывает стандартную функцию getProducts. Что же требуется сделать для того, чтобы убрать товар с ценой “0” в конец списка?

Находим модель плагина bf, находится он по следующему адресу:

/catalog/model/extension/module/brainyfilter.php

Ищем функцию prepareQueryForCategory(), выглядит она так:

  public function prepareQueryForCategory()
    {
        $sql = $this->_prepareFilterQuery()->limit($this->productsLimit, $this->productsStart);
        
        $sql->innerJoin(array('pd' => 'product_description'), 'pd.product_id = p.product_id')
            ->where('pd.language_id = ?', (int)$this->config->get('config_language_id'));
        switch ($this->sortBy) 
        {
            case 'pd.name' : {
                $sql->order(array("LCASE(pd.name) {$this->order}"));
                break;
            }
            case 'p.model' : {
                $sql->select(array('pp.model'))->order(array("LCASE(pp.model) {$this->order}"))
                    ->innerJoin(array('pp' => 'product'), 'pp.product_id = p.product_id');
                break;
            }
            case 'p.quantity' : {
                $sql->select(array('pp.quantity'))->order(array("pp.quantity {$this->order}", ))
                    ->innerJoin(array('pp' => 'product'), 'pp.product_id = p.product_id');
                break;
            }
            case 'p.price' : {
                if (self::$SKIP_TMP_TABLE) {
                    $this->_applyPriceFilterCondition($sql);
                }
                $sql->order(array("actual_price {$this->order}"));
                break;
            }
            case 'rating' : {
                $sql->leftJoin(array('f' => self::TBL_FILTER), 'f.product_id = p.product_id')
                    ->where('f.filter_group = "r0"')
                    ->order(array("f.filter_id {$this->order}"));
                break;
            }
            case 'p.sort_order' : {
                $sql->select(array('pp.sort_order'))->order(array("pp.sort_order {$this->order}"))
                    ->innerJoin(array('pp' => 'product'), 'pp.product_id = p.product_id');
                break;
            }
            case 'p.date_added' : {
                $sql->select(array('pp.date_added'))->order(array("pp.date_added {$this->order}"))
                    ->innerJoin(array('pp' => 'product'), 'pp.product_id = p.product_id');
                break;
            }
        }
        
        if ($this->sortBy !== 'pd.name') {
            $sql->order(array("pd.name {$this->order}"));
        } 
        
        return (string)$sql;
    }
    

и после фрагмента:

        if ($this->sortBy !== 'pd.name') {
            $sql->order(array("pd.name {$this->order}"));
        } 

вставляем следующий код:

	if ($this->sortBy == 'p.price') {
		$sql = (string)$sql;
		$pos = strrpos($sql, 'ORDER BY');
		if ($pos !== false) {
			$sql1 = substr($sql,0,$pos);
			$sql2 = str_replace(', pd.name ' . $this->order, '' ,substr($sql,$pos-1 + 9));
			$sql3 = "SELECT * from (" . $sql1 . ") pt " . " ORDER BY actual_price = 0, " . $sql2;
			$sql = $sql3;
		}
	}

Не вижу смысла перестраивать запрос, проще сделать так, пускай и код будет не самым красивым.
Аналогично с первым способом, сохраняем, обновляем файл на Вашем сайте. Не забываем обновлять кеш модификаторов! Готово! Теперь мы подружили Brainy Filter c нужной нам сортировкой нулевой цены.

Протестировано на OcStore 2.3

Дата создания статьи: 05.06.2021

Поделиться статьей:
Share on vk
Share on telegram
Share on twitter
Share on facebook
Share on linkedin
Share on reddit
Share on pinterest
Share on tumblr
Share on whatsapp
Share on skype
Share on email

Оставьте Ваше сообщение

Комментарии

Подписаться
Уведомить о
guest
2 Комментарий
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
Денис
Денис
18 дней назад

Спасибо большое, очень помогли!

Ознакомьтесь с другими работами

Смотрите далее

2
0
Поделиться своими мыслямиx
()
x
Открыть чат
Нужна помощь?
Powered by