Перейти к содержимому


Фотография
- - - - -

Произвольная сортировка каталога с фронта. ХАК. Делаем сами.

сортировка

Сообщений в теме: 7

#1 Ёшкин Кот

Ёшкин Кот

Отправлено 12 June 2016 - 14:55

*
Популярное сообщение!

Разберемся как сделать произвольную быструю сортировку для каталога. Примерно такую как на картинках. (Стили и вывод можно настроить самому).

 

Прикрепленный файл  1b652db1f9.jpg   192.99К   0 Количество загрузок:Прикрепленный файл  fe708569db.jpg   192.41К   0 Количество загрузок:

 

Прежде всего определяемся какие сортировки будут нужны

 

в нашем случае:

 

по возрастанию цены
по убыванию цены
по популярности
по дате добавления (сначала новые)
по дате добавления (сначала старые)
 
Первым делом будем править файлы в темплейте JBZoo (В моем случае это темплейт по умолчанию Default (Catalog))
 
media\zoo\applications\jbuniversal\templates\catalog\category.php - для вывода сортировки каталога
media\zoo\applications\jbuniversal\templates\catalog\filter.php - для вывода сортировки результатов поиска
 
media\zoo\applications\jbuniversal\templates\catalog\category.php 
 
В место, где надо вывести сортировку вставляем блок:
 
//Шаблон для сортировок в каталоге ======================================================================
if ($this->app->zoo->getApplication()->id == 1) { //проверяем в каком приложении мы находимся

// Получаем URL где находимся

$myuri = JFactory::getURI();
$myurl = $myuri->toString(array('path', '', 'fragment'));

$currentorder = $_SESSION['orderkit'];
if (!$currentorder) {$currentorder = 'price_asc';} //устанавливаем значение сортировки по умолчанию.

//Вывод сортировки
?>
    <div class="orderblock">
<span class="ordertitle">Сортировать</span>
        <span class="searchsel">
<ul>
<li <?php if ($currentorder == "price_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=price_asc" class="price asc">c начала дешевые</a></li>
<li <?php if ($currentorder == "price_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=price_desc" class="price desc">c начала дорогие</a></li>
<li <?php if ($currentorder == "popular_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=popular_desc" class="popular desc">c начала популярные</a></li>
<li <?php if ($currentorder == "date_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=date_desc" class="date desc">c начала новые</a></li>
<li <?php if ($currentorder == "date_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=date_asc" class="date asc">c начала старые</a></li>
</ul>
        </span>
</div>
    <?php

}
//Шаблон для сортировок в каталоге ======================================================================
 

У меня это 55 строчка. 

 

сразу же после строк:

    // category items render
    if ($this->params->get('config.items_show', 1) && count($this->items)) {

Далее правим media\zoo\applications\jbuniversal\templates\catalog\filter.php

 

В место где необходимо вывести сортировку вставляем этот блок:

	//Шаблон для сортировок в фильтре ======================================================================

	if ($this->app->zoo->getApplication()->id == 1) { //проверяем в каком приложении мы находимся

	// Получаем URL где находимся
	$myuri = JFactory::getURI();
	$myurl = $myuri->toString(array('path', 'query', 'fragment'));
	
	$currentorder = $_SESSION['orderkit'];
	if (!$currentorder) {$currentorder = 'price_asc';} //устанавливаем значение сортировки по умолчанию.
	
	//Вывод сортировки	
	?>
    <div class="orderblock">
		<span class="ordertitle">Сортировать</span>
		<span class="searchsel">
        <ul>
			<li <?php if ($currentorder == "price_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>&orderkit=price_asc" class="price asc">c начала дешевые</a></li>
			<li <?php if ($currentorder == "price_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>&orderkit=price_desc" class="price desc">c начала дорогие</a></li>
			<li <?php if ($currentorder == "popular_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>&orderkit=popular_desc" class="popular desc">c начала популярные</a></li>
			<li <?php if ($currentorder == "date_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>&orderkit=date_desc" class="date desc">c начала новые</a></li>
			<li <?php if ($currentorder == "date_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>&orderkit=date_asc" class="date asc">c начала старые</a></li>
		</ul>	
        </span>
	</div>
    <?php
	}

	//Шаблон для сортировок в каталоге ======================================================================

У меня по условиям дизайна блок выводится над заголовком (24 строка).

 

заголовок:

?><h1 class="title"><?php echo JText::_('JBZOO_SEARCH_RESULT'); ?></h1><?php

Эти блоки отличаются друг от друга. Они не взаимозаменяемые. Основное отличие в формировании ссылок и изначального адреса ссылки.

 

В первом случае ?orderkit=price_asc для категории и &orderkit=price_asc для поиска. 

 

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

    <div class="orderblock">
		<span class="ordertitle">Сортировать</span>
        <span class="searchsel">
		<ul>
			<li <?php if ($currentorder == "price_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=price_asc" class="price asc">c начала дешевые</a></li>
			<li <?php if ($currentorder == "price_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=price_desc" class="price desc">c начала дорогие</a></li>
			<li <?php if ($currentorder == "popular_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=popular_desc" class="popular desc">c начала популярные</a></li>
			<li <?php if ($currentorder == "date_desc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=date_desc" class="date desc">c начала новые</a></li>
			<li <?php if ($currentorder == "date_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=date_asc" class="date asc">c начала старые</a></li>
		</ul>
        </span>	
	</div>

Данные блоки надо редактировать под себя перечисляя в них свои сортировки. Я делал через ul li список. Вы форматируйте как вам угодно.

 

Так выглядит строка:

 

<li <?php if ($currentorder == "price_asc") {print 'class="active"';} ?>><a href="<?php print $myurl; ?>?orderkit=price_asc" class="price asc">c начала дешевые</a></li>

 

Я выделил цветом ключевые переменные. В данном случае price_asc

 

Эта переменная будет передана в адресе при клике на соответствующий пункт сортировки c начала дешевые

 

Вы создаете любой набор сортировок со своими переменными. У меня:

 

по возрастанию ценыprice_asc
по убыванию цены price_desc
по популярностиpopular_desc
по дате добавления (сначала новые)date_desc
по дате добавления (сначала старые)date_asc

 

Стили внешнего вида пока не настраиваем. Для начала запустим, чтобы все это дело заработало.

 

Переходим к правке файлов отвечающих за сортировку. Это:

 

components\com_zoo\controllers\default.php - отвечает за сортировку категории

media\zoo\applications\jbuniversal\framework\controllers\search.php - сортировка результатов поиска

 

components\com_zoo\controllers\default.php открываем данный файл.

 

ищем строку:

$this->item_order = $params->get('config.item_order');

У меня это оказалась 228 строка. После нее вставляем следующий код:

		//Блок сортировок для каталога---------------------------------------------
		if ($this->app->zoo->getApplication()->id == 1) { //проверяем в каком приложении мы находимся
		//jbdump ($this->item_order,0); //Используйте эту строку, если у вас подключен JBdump
		//echo '<pre>';print_r ($this->item_order);echo '</pre>'; //Используйте эту строку, если у вас не подключен JBdump покажет значения выбраной сортировки
		//print 'Текущее значение сессии сортировки: '.$_SESSION['orderkit']; //Посмотреть текущее значение сессии для сортировки
		if ($_SESSION['orderkit'] == "") {$_SESSION['orderkit'] = 'price_asc';} //устанавливаем значение сортировки по умолчанию.
		//Получаем переменную для направления сортировки 
		if (isset($_GET['orderkit'])) { $_SESSION['orderkit'] = $_GET['orderkit'];} //Меняем сортировку, если есть ключ в URL

			if (isset($_SESSION['orderkit'])) {
				
				switch ($_SESSION['orderkit']) {
					case 'price_asc':
						$this->item_order = array(
						'_jbzoo_0_field_01ab859d-e9ce-42a3-b24b-4d11422bba90___value',
						'_jbzoo_0_mode_n',
						'_jbzoo_0_order_asc'
						);	
					break;
					case 'price_desc':
						$this->item_order = array(
						'_jbzoo_0_field_01ab859d-e9ce-42a3-b24b-4d11422bba90___value',
						'_jbzoo_0_mode_n',
						'_jbzoo_0_order_desc'
						);		
					break;
					case 'popular_desc':
						$this->item_order = array(
						'_jbzoo_0_field_corehits',
						'_jbzoo_0_mode_n',
						'_jbzoo_0_order_desc'
						);		
					break;
					case 'date_asc':
						$this->item_order = array(
						'_jbzoo_0_field_corecreated',
						'_jbzoo_0_mode_d',
						'_jbzoo_0_order_asc'
						);		
					break;
					case 'date_desc':
						$this->item_order = array(
						'_jbzoo_0_field_corecreated',
						'_jbzoo_0_mode_d',
						'_jbzoo_0_order_desc'
						);	
					break;						
					}
			}
			}
			
		//jbdump ($this->item_order,0); //Используйте эту строку, если у вас подключен JBdump
		//echo '<pre>';print_r ($this->item_order);echo '</pre>'; //Используйте эту строку, если у вас не подключен JBdump покажет значения выбраной сортировки						
		
		//Блок сортировок для каталога---------------------------------------------	

Здесь видим следующие блоки:

case 'price_asc':
	$this->item_order = array(
	'_jbzoo_0_field_01ab859d-e9ce-42a3-b24b-4d11422bba90___value',
	'_jbzoo_0_mode_n',
	'_jbzoo_0_order_asc'
	);	
break;

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

 

case 'price_asc': - Определяет какую переменную будет обрабатывать данный блок. В нашем случае price_asc то есть по возрастанию цены

 

Следовательно нам нвдо заставить каталог сортироваться по нужному элементу цены в нужном порядке. Как его найти?

 

Для этого в блоке я сделал несколько строчек. Они по умолчанию закомментированы.

//jbdump ($this->item_order,0); //Используйте эту строку, если у вас подключен JBdump
//echo '<pre>';print_r ($this->item_order);echo '</pre>'; //Используйте эту строку, если у вас не подключен JBdump покажет значения выбраной сортировки
//print 'Текущее значение сессии сортировки: '.$_SESSION['orderkit']; //Посмотреть текущее значение сессии для сортировки

Будем считать, что JBdump нам не доступен. Раскомментируем вторую строку убрав // перед ней

//jbdump ($this->item_order,0); //Используйте эту строку, если у вас подключен JBdump
echo '<pre>';print_r ($this->item_order);echo '</pre>'; //Используйте эту строку, если у вас не подключен JBdump покажет значения выбраной сортировки
//print 'Текущее значение сессии сортировки: '.$_SESSION['orderkit']; //Посмотреть текущее значение сессии для сортировки

сохраняем все это дело

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

Прикрепленный файл  867833d6cb.jpg   121.88К   0 Количество загрузок:

Сохраняем. Обновляем страницу каталога и получаем нечто такое:

Прикрепленный файл  085316a3cb.jpg   169.95К   0 Количество загрузок:

 

Это сортировка выбранная нами в админке. Мы видим ID элемента, тип сортировки и ее направление:

[0] => _jbzoo_0_field_433a0a0e-30e8-4e71-92ab-4b9eb0d678f7___value
[1] => _jbzoo_0_mode_n
[2] => _jbzoo_0_order_asc

переносим значения сортировкив наш блок
case 'price_asc':
    $this->item_order = array(
        '_jbzoo_0_field_433a0a0e-30e8-4e71-92ab-4b9eb0d678f7___value',
        '_jbzoo_0_mode_n',
        '_jbzoo_0_order_asc'
);
break;

Таким образом создаем все блоки обработки наших сортировок. 

То есть столько блоков сколько мы создали в шаблонах столько делаем в данном месте и настраиваем их изменяя сортировки в админке для каталога для вывода необходимых нам данных для блоков.

 

Параллельно проверяем работоспособность соответствующих сортировок используя созданные нами ссылки в каталоге.

 

После настройки фильтра в категориях каталога комментируем снова строчку для вывода переменных сортировок и переходим к настройке фильтра для результатов поиска.

 

Открываем файл media\zoo\applications\jbuniversal\framework\controllers\search.php

 

находим строку:

$appId    = $this->_jbrequest->get('app_id');

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

		//Блок сортировок для фильтра---------------------------------------------
		//jbdump ($order,0); //Используйте эту строку, если у вас подключен JBdump
		//echo '<pre>';print_r ($order);echo '</pre>'; //Используйте эту строку, если у вас не подключен JBdump покажет значения выбраной сортировки
		//print 'Текущее значение сессии сортировки: '.$_SESSION['orderkit']; //Посмотреть текущее значение сессии для сортировки

		if ($this->app->zoo->getApplication()->id == 1) { //проверяем в каком приложении мы находимся
		
		if ($_SESSION['orderkit'] == "") {$_SESSION['orderkit'] = 'price_asc';} //устанавливаем значение сортировки по умолчанию.
		//Получаем переменную для направления сортировки 
		if (isset($_GET['orderkit'])) { $_SESSION['orderkit'] = $_GET['orderkit'];} //Меняем сортировку, если есть ключ в URL
		
			if (isset($_SESSION['orderkit'])) {
					switch ($_SESSION['orderkit']) {
					case 'price_asc':
						$order[field] = '01ab859d-e9ce-42a3-b24b-4d11422bba90___value';
						$order[mode] = 'n';
						$order[order] = 'asc';
						break;
					case 'price_desc':
						$order[field] = '01ab859d-e9ce-42a3-b24b-4d11422bba90___value';
						$order[mode] = 'n';
						$order[order] = 'desc';	
						break;
					case 'popular_desc':
						$order[field] = '_jbzoo_0_field_corehits';
						$order[mode] = 'n';
						$order[order] = 'desc';	
						break;
					case 'date_asc':
						$order[field] = 'corecreated';
						$order[mode] = 'd';
						$order[order] = 'asc';
						break;
					case 'date_desc':
						$order[field] = 'corecreated';
						$order[mode] = 'd';
						$order[order] = 'desc';
						break;						
					}
			}
		}

Здесь блоки обработки сортировок выглядят иначе:

case 'price_asc':
     $order[field] = '01ab859d-e9ce-42a3-b24b-4d11422bba90___value'; 
     $order[mode] = 'n'; 
     $order[order] = 'asc'; 
break;

если сравнить их с уже настроенными блоками то мы увидим, что разница не так и велика.

 
для каталога:
 
case 'price_asc':
    $this->item_order = array(
        '_jbzoo_0_field_433a0a0e-30e8-4e71-92ab-4b9eb0d678f7___value',
        '_jbzoo_0_mode_n',
        '_jbzoo_0_order_asc'
);
break;

Для поиска

:

case 'price_asc':
        $order[field] = '01ab859d-e9ce-42a3-b24b-4d11422bba90___value';
        $order[mode] = 'n';
        $order[order] = 'asc';
break;

 

То есть здесь просто иначе формируется массив и обрезаны префиксы для элементов.

Можно изменить уже готовые блоки.

 

После этого можно настроить стили для фильтра. На картинках стили представлены ниже:

.orderblock {
    border-top: 1px solid #c7c7c7;
    float: left;
    width: 100%;
    padding: 10px 0;
	text-align:right;
}
.orderblock .searchsel {
    display: inline-block;
    float: right;
    margin: 0;
    padding: 5px 15px;
    border: 1px solid #c7c7c7;
    height: 35px;
    position: relative;
    overflow: hidden;
    border-radius: 20px;
	text-align:left;
	background: url("../images/drop.png") no-repeat right;	
	width: 200px;
}
.orderblock .searchsel:hover {
    overflow: visible;
	border-radius:20px 20px 0 0;	
}
span.searchsel ul {
    position: absolute;
    top: 33px;
    right: -1px;
    left: -1px;
    border: 1px solid #c7c7c7;
    border-top: none;
    z-index: 50;
    background: #fff;
    padding: 15px;
    border-radius: 0 0 20px 20px;
}
.orderblock ul li {
    list-style: none;
    padding: 5px;
}
.orderblock ul li:hover a {
    color: #999;
}
.orderblock li.active {
	position:absolute;
    top: -34px;
}
.orderblock li a {
	color:#000;
}
span.ordertitle {
    display: inline-block;
    padding: 5px 20px;
}
#yoo-zoo > div.category {
    margin: 0;
    padding: 0;
}

Обратите внимание на следующие строки в коде:

if ($this->app->zoo->getApplication()->id == 1) { //проверяем в каком приложении мы находимся

Этим условием обернут весь код блоков сортировок и определяет в каком приложении выводится работает это все дело. Иначе сортировки будут выводится везде и работать например в блоге если он отдельным приложением сделан. Так же в данном месте можно поставить условие по категориям или иные условия для ограничения работы сортировок.. 

 
Файлы: Прикрепленный файл  files-sotr.zip   12.22К   29 Количество загрузок:

Прикрепленные файлы

  • Прикрепленный файл  e0cf56e9a1.jpg   133.21К   0 Количество загрузок:

Сообщение отредактировал Ёшкин Кот: 12 June 2016 - 16:26

  • 15

#2 fiction13

fiction13

Отправлено 12 June 2016 - 17:00

*
Популярное сообщение!

Начал писать подробное FAQ по этой теме, но раз Вы написали, то думаю, что уже не допишу.

 

Переменные из сессии и GET лучше (читай безопаснее) брать с помощью стандартных функций Joomla.

 

А так да, принцип описан верный. По такому же принципу вешается селект с выбором количества товаров для отображения.


  • 5

#3 Ёшкин Кот

Ёшкин Кот

Отправлено 12 June 2016 - 19:46

Я еще не прокачался на столько.. корректировки приветствуются.

 

 Вообще идеально было бы написать скрипт, при котором бы автоматом брало сортировки все из настройки сортировок из шаблона и выводило в фильтре и организовывало сортировку из всех выбранных.


Сообщение отредактировал Ёшкин Кот: 12 June 2016 - 19:49

  • 2

#4 fiction13

fiction13

Отправлено 13 June 2016 - 08:22

*
Популярное сообщение!

Я еще не прокачался на столько.. корректировки приветствуются.

Это ж несложно.

 

Берем переменную из GET

JFactory::getApplication()->input->getString('order', '');

Берем значение из сессии

JFactory::getSession()->get('order')

Пихаем значение в сессию

JFactory::getSession()->set('order', 'ЗНАЧЕНИЕ');

  • 6

#5 Alex Def

Alex Def

Отправлено 05 September 2016 - 00:32

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

Попробовал создать элемент ядра Zoo, который подхватывал бы значение элемента цены у любого типа материала. С помощью кода подсказанного fiction13:

foreach($this->_item->getElements() as $element) {
	if($element->config->type == 'jbpriceplain') {
		$price = trim($element->getList()->getTotal()->plain('RUB'));
		$price = $price ? (int)str_ireplace(' ', '', $price) : 'empty';
	}
}

Всё бы круто работало, но оказывается сортировка Zoo происходит при запросе к БД (вот так открытие =)), из-за чего возникает ошибка 1054 - неизвестный столбец.

В итоге мне удалось запихнуть искомое значение цены лишь в столбец created_by_alias и... сортировка заработала для всех типов материалов в категории! Но тут два очевидных минуса: значение записывается только при пересохранении материала, т.к. при создании материала элемент цены ещё пустой. А второй минус появляется если в каталоге используется несколько разных валют, — значение записывается с текущим курсом и не обновляется при изменение этого самого курса.

 

Так вот к чему я всё это. Всё описание выше я проделывал стандартными средствами Zoo. И судя по тому, что в JBZoo сортировки работают по любым полям, вытекает такой вопрос: а есть ли возможность создать такой же элемент ядра jbzoo (с одинаковым ID для всех типов материалов, так сказать)?


Сообщение отредактировал Alex Def: 05 September 2016 - 00:53

  • 0

#6 Alex Def

Alex Def

Отправлено 09 October 2016 - 15:29

Господа, так как быть если в одной категории несколько типов товаров?


  • 1

#7 SmetDenis

SmetDenis

Отправлено 10 October 2016 - 08:07

Господа, так как быть если в одной категории несколько типов товаров?

 

К сожалению, сортировка как и фильтр работает в рамках только одного типа материала.

Наследие компонента ZOO...


  • 0
JBZoo v4.0 и новый чудный мир Open Source GPL
Отключайте проверку лицензий как моно скорее!


— Есть два типа людей: Кто еще не делает бекапы и кто уже делает бекапы.


#8 Alex Def

Alex Def

Отправлено 10 October 2016 - 08:48

Есть проекты на 2.1.5. Там конечно jbprice advance, но движок воспринимает его как одно целое. Можно в настройках приложения указать jbprice от одного типа материалов — сортироваться корректно будут все, это касается и сортировок в модулях. И при пересечениях никаких проблем.

 

Так что это больше похоже на "наследие" v2.2.0.


  • 0





Темы с аналогичным тегами сортировка

Click to return to top of page in style!