Вывод фильтров для всех разделов каталога

Материал из Umicms
Версия от 15:33, 23 сентября 2013; Mad grant (обсуждение | вклад)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к:навигация, поиск

Актуально для версии 2.9.1

Вывод фильтров для всех разделов каталога

По-умолчанию в демошаблоне "demodizzy"(Современный интернет магазин) реализована следующая структура каталога:

Structure.png

И фильтры выводятся только в разделах каталога 3его уровня, а в разделах 2ого уровня фильтры не выводятся:

Filter1.pngFilter4.png

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

Решение через макрос catalog getObjectList

Сначала, попробуем решить задачу с помощью системного макроса %catalog getObjectList()%, см. "Полезные ссылки". Попробуем воспользоваться примером решения из статьи Как_вывести_фильтр_по_товарам_по_всему_каталогу(XSLT), для этого перед вызовом макроса %catalog search()%, см. "Полезные ссылки", в файле /templates/demodizzy/xslt/modules/catalog/category-view.xsl

        <xsl:apply-templates select="document('udata://catalog/search')" />

добавим переменную "type" и присвоим ей значение типа данных первого объекта каталога, полученного с помощью catalog getObjectList:

        <xsl:variable name="type" select="document(concat('udata://catalog/getObjectsList/', page/@id, '////3/'))/udata/type_id"/>

и модифицируем вызов макроса catalog search, добавив 4 параметром нашу переменную "type"

        <xsl:apply-templates select="document(concat('udata://catalog/search////', $type))"/>

то есть в результате темплейт match="udata[@method = 'getObjectsList'][total]" будет начинаться со следующего:

        <xsl:variable name="type" select="document(concat('udata://catalog/getObjectsList/', page/@id, '////3/'))/udata/type_id"/>
        <xsl:apply-templates select="document(concat('udata://catalog/search////', $type))"/>

Результат

В результате страницах разделов каталога 2ого и 3его уровня отображаются фильтры, причем для каждого раздела каталога свои:

Filter2.pngFilter3.png

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

Filter5.png

Нас это не устраивает, так как, хотелось бы, чтобы форма осталась и пользователь мог ввести другие данные. Такая ситуация возникает из-за особенностей работы макроса catalog getObjectsList(), он взаимодействует с get параметрами, появляющимися в адресной строке браузера после применения фильтра, а так как ни один объект каталога не удовлетворяет заданным параметрам, то и переменную type равную типу данных объекта каталога мы получить не можем, а значит мы передаем макросу catalog search() пустую переменную, то и форма не выводится. Значит нам нужно получать тип данных каким-нибудь другим способом, независимым от работы catalog search(), из стандартных средства с этой задаче справиться USel, см. "Полезные ссылки".

Решение через USel

Сначала, создадим xml шаблон для USel выборки, для этого поместим в директорию /templates/demodizzy/usels/ файл getObjectOfCategory.xml следующего содержания:

<?xml version="1.0" encoding="utf-8"?>
<selection>
        <!-- результат выборки - страницы -->
	<target result="pages">
                        <!-- результат выборки - страницы объектов каталога -->
			<type module="catalog" method="object" />
                        <!-- результат выборки - страницы объектов каталога, находящиеся в директории с id или url равным {1} на 5 уровнях вложенности -->
			<category depth="5">{1}</category>
	</target>
        <!-- выводить только один результат выборки -->
	<limit page="0">1</limit>
</selection>

А теперь заменим присваивание переменной type значения через catalog getObjectsList() в файле /templates/demodizzy/xslt/modules/catalog/category-view.xsl

        <xsl:variable name="type" select="document(concat('udata://catalog/getObjectsList/', page/@id, '////3/'))/udata/type_id"/>

на присваивания через usel:

        <xsl:variable name="type" select="document(concat('usel://getObjectOfCategory/', $document-page-id))/udata/page/@type-id"/>

в этом селекте мы используем переменную $document-page-id, которая стандартно задана в файле /templates/demodizzy/xslt/default.xsl:

        <xsl:variable name="document-page-id" select="/result/@pageId" />

и передаем её первым параметром {1} в наш USel.

Результат

В результате, вывод формы фильтрации не зависит от введенных раннее данных. Однако, usel это не оптимальное решение, так как он довольно медленный, лучше решить нашу задачу через API.

Решение через API

В кастоме мы будем с помощью Selector, см. "Полезные ссылки", получать объект каталог из раздела с заданным id, а потом с помощью метода getObjectTypeId класса umiHierarchyElement, см. "Полезные ссылки". получать id его типа данных, собственно его кастом и будет возвращать. В файле /classes/modules/catalog/__custom.php после строки abstract class __custom_catalog { добавим следующий код:

public function getObjectsType($id)
		{
		// создаем $pages экземпляр класса selector
		$pages = new selector('pages');
		// определяем типы данных - объект каталога
		$pages->types('object-type')->name('catalog', 'object');
		// определяем параметры выборки - искать объекты каталога, дочерние страницы с id = $id с вложенностью в 5 уровней
		$pages->where('hierarchy')->page($id)->childs(5);
		// определяем выводимое количество результатов выборки - 1 результат
		$pages->limit(0,1);
		// см. "Полезные ссылки"
		foreach($pages as $page)
		// возвращаем тип данных полученной страницы
		return $page->getObjectTypeId();
		}

и добавим созданному методу права, чтобы пользователи тоже могли наблюдать результат его работы, для этого приведем содержание файла /classes/modules/catalog/permissions.custom.php (если такого файла нет, то создайте его) к следующему виду:

<?php
	// В этом файле вы можете расширить существующую группу прав, или добавить свою
	$permissions = array(
		'tree' => array('getObjectsType'),
		'view' => array('getObjectsType')
	);
?>

После этого, заменим присваивание переменной type значения через USel в файле /templates/demodizzy/xslt/modules/catalog/category-view.xsl:

        <xsl:variable name="type" select="document(concat('usel://getObjectOfCategory/', $document-page-id))/udata/page/@type-id"/>

на присваивание через наш кастомный макрос:

        <xsl:variable name="type" select="document(concat('udata://catalog/getObjectsType/', $document-page-id))/udata"/>

Результат

Результат будет такой же как через usel, только мы выиграем в быстродействии.

Полезные ссылки

  • Документация по макросу %catalog getObjectList()% [1]
  • Документация по макросу %catalog search()% [2]
  • Документация по протоколу USel [3]
  • Документация по Selector [4]
  • Документация по классу umiHierarchyElement [5]
  • Конструкция foreach [6]