mFilter2 - фильтрация категорий по дочерним товарам

Публикую решение довольно распространённой задачи. Нужно фильтровать товары, но выводить не их, а их категории. Таким образом получается фильтр категорий, но по свойствам их дочерних товаров.

Первым делом нужно разобраться в логике работы mFilter2:
  1. Фильтр использует для поиска и вывода ресурсов один сниппет, указанный в &elements. В случае работы с товарами там обычно указывается msProducts.
  2. К этому сниппету будет 2 обращения: предварительная выборка и возврат подходящих id товаров, а затем их вывод пользователю.
  3. Различить эти два запроса можно по присылаемому параметру returnIds.
В получение id товаров нам вмешиваться не нужно, потому что фильтр должен построить из них фильтры. Нам нужно изменить только вывод этих товаров, заменив их на категории.

Пишем новый сниппет msProductsCategories:
<?php
// Он работает только, если это вывод товаров, а не запрос подходящих id
if (empty($returnIds)) {
	// Присоединяем таблицу категорий
	if (empty($innerJoin) || !$where = $modx->fromJSON($innerJoin)) {
		$innerJoin = array();
	}
	$innerJoin['Category'] = array(
		'class' => 'msCategory',
	);
	$scriptProperties['innerJoin'] = $modx->toJSON($innerJoin);
	// Группируем по категории
	$scriptProperties['groupby'] = 'Category.id';
	// Заменяем поля товаров полями категорий
	$scriptProperties['select'] = $modx->toJSON(array(
		'Category' => '*',
		// Можно переопределить еще и выборку полей товара, чтобы были с префиксом,
		// но я это закомментировал, потому что поля Data и так доступны, а товары не нужны
		//'msProduct' => $modx->getSelectColumns('msProduct', 'msProduct', 'product.'),
		//'Data' => $modx->getSelectColumns('msProductData', 'Data', 'data.'),
	));
}

// Мы добавили свой опции, а дальше пусть работает стандартный сниппет
return $modx->runSnippet('msProducts', $scriptProperties);
Как видите, всё работает через стандартные параметры pdoTools, никаких хаков.

Остаётся только указать этот новый сниппет при вызове mFilter2:
[[!mFilter2?
	&class=`msProduct`
	&element=`msProductsCategories`
	&parents=`0`
	&filters=`
		ms|price:number,
		msoption|tags,
		ms|vendor:vendors,
		ms|old_price:boolean,
	`
	&tpl=`@INLINE <p>
		<a href="{$uri}">
			<img src="{$thumb ?: '/assets/components/minishop2/img/web/ms2_small.png'}">
			{$pagetitle}
		</a>
	</p>`
	&tplFilter.outer.ms|price=`tpl.mFilter2.filter.slider`
	&tplFilter.row.ms|price=`tpl.mFilter2.filter.number`
]]

Получившееся решение не меняет исходников и переживёт любое обновление системы. Временно потестить можно на minishop2.com/test
Василий Наумкин
11 октября 2015, 07:25
modx.pro
22
4 175
+4

Комментарии: 6

Василий Столейков
11 октября 2015, 11:02
0
Интересно, спасибо за это решение!
Правда подсказки о выводе количества результатов настроены на товары, а не на категории. Но их можно отключить, чтобы не вводили в заблуждение. )
    Василий Наумкин
    11 октября 2015, 11:49
    +2
    С одной стороны, может и непривычно, но зато правильно — ведь фильтруются товары, а не категории, и ты видишь сколько всего остаётся именно товаров.

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

    Категорий обычно не очень много, так что показ предсказаний им не нужен.
    Серьёзный
    03 ноября 2015, 20:03
    0
    Отличное решение, спасибо!

    Василий, можно ли вас попросить написать решение для сортировки Товаров по параметрам Категорий?

    К примеру:
    Категория «Здание» с товаром «Помещение».
    У здания ТВ поле со значением метро.
    Нужно вывести mFilter с помещениями, у родителей которых метро = «Невский проспект».
      Evgeny Tarasov
      22 ноября 2016, 12:34
      0
      Добрый день!
      При помощи данного решения по фильтру выдаются товары, только с названиями категорий.
      например, если у меня 3 категории и в каждом по 4 товара, то выведется 12 товаров с названиями своих категорий
      А можно сделать так, что бы выводились только категории (по примеру чуть выше — 3 категории) но их нужно фильтровать по свойствам дочерних товаров.
        yuri
        22 февраля 2020, 23:00
        0
        не нашли решение?
        yuri
        22 февраля 2020, 22:56
        0
        Очень, полезная штука.
        Проблема, с которой столкнулись — сколько товаров, столько раз вывелся родитель, хотя он один. то есть если в него вложено 10 товаров, то в результате — мы видим 10 раз вывод одного родителя.
          Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
          6