Вывод фильтров для всех разделов каталога
Актуально для версии 2.9.1
Содержание
Вывод фильтров для всех разделов каталога
По-умолчанию в демошаблоне "demodizzy"(Современный интернет магазин) реализована следующая структура каталога:
И фильтры выводятся только в разделах каталога 3его уровня, а в разделах 2ого уровня фильтры не выводятся:
А нам нужно вывести фильтры для товаров и на 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его уровня отображаются фильтры, причем для каждого раздела каталога свои:
На первый взгляд задача была решена, но если мы зададим в фильтре такие значения, которым не будет удовлетворять ни один объект каталога (товар), то после нажатия кнопки "применить", окно фильтра пропадет, а так как и объектов нет - пользователю откроется пустой экран:
Нас это не устраивает, так как, хотелось бы, чтобы форма осталась и пользователь мог ввести другие данные. Такая ситуация возникает из-за особенностей работы макроса 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, только мы выиграем в быстродействии.