Облако тегов для miniShop2
UPDATE 20.03.2018: Сниппет обновлён на корректный и добавлен pdoTools для обработки чанка.
Появилась задача реализовать облако тегов для удобства поиска товаров в интернет-магазине. Для этого сделал простенький сниппет, где теги собираются со всех товаров на сайте.

Сниппет умеет принимать параметры базового размера(font), шага в пикселях(step), количества размеров(levels) и чанка для вывода(tpl).
Алгоритм работы прост:
1. Собираются теги со всех товаров сайта.
2. Подсчитывается количество товаров для каждого тега.
3. Рассчитываются размеры для каждого уровня и границы по количеству использования тега.
4. Если не указан шаблон вывода, то на экране также будет облако тегов, но без ссылок.
В чанке для вывода доступны плейсхолдеры:
Вызывать так:
Сам сниппет msCloudTags:
P.S.: У сайта на скриншоте товары только добавляются, большинство тегов используются 1-3 раза, а те, что крупные, больше 20 раз.
P.P.S.: Наверняка, код можно написать покороче и лучше, но я совсем недавно начал работать на MODX. Буду рад вопросам и замечаниям :)
UPDATE 20.03.2018: Сниппет обновлён на корректный и добавлен pdoTools для обработки чанка.
Появилась задача реализовать облако тегов для удобства поиска товаров в интернет-магазине. Для этого сделал простенький сниппет, где теги собираются со всех товаров на сайте.

Сниппет умеет принимать параметры базового размера(font), шага в пикселях(step), количества размеров(levels) и чанка для вывода(tpl).
Алгоритм работы прост:
1. Собираются теги со всех товаров сайта.
2. Подсчитывается количество товаров для каждого тега.
3. Рассчитываются размеры для каждого уровня и границы по количеству использования тега.
4. Если не указан шаблон вывода, то на экране также будет облако тегов, но без ссылок.
В чанке для вывода доступны плейсхолдеры:
[[+fontlevel]] //число от 0 до levels, можно использовать для класса level1, level2
[[+tag]] // сам тэг
[[+fontsize]] // размер в пикселях Вызывать так:
[[msCloudTags? &tpl=`tpl.tag` &font=`13` &step=`2` &levels=`10`]]Сам сниппет msCloudTags:
<?php
if (!isset($step)) {$step = 2;} // шаг в пикселях
if (!isset($font)) {$font = 12;} // начальный размер шрифта
if (!isset($levels)) {$levels = 10;} // максимальное число уровней
if (!isset($key)) {$key = 'tags';}
if (!isset($tpl)) {$tpl = '@INLINE <span class="level{$fontlevel}" style="font-size:{$fontsize}px;">{$tag}</span>;';}
$pdo = $modx->getService('pdoTools');
$q = $modx->newQuery('msProductOption');
$q->innerJoin('modResource','modResource','modResource.id = msProductOption.product_id');
$q->where(array('msProductOption.key' => $key));
$q->select(array('msProductOption.value'));
$q->sortby('msProductOption.value','ASC');
$tags = array();
if ($q->prepare() && $q->stmt->execute()) {
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$tags[]= $row['value'];
}
}
$tagsCount = array_count_values($tags); // массив с подсчитанным вхождением
$maxCount = max($tagsCount); // максимальное количество вхождений
$minCount = min($tagsCount); // минимальное
$fontSizes[] = $font;
for ($i=0;$i<$levels;$i++) {
$fontSizes[] = $font+=$step;
}
$fontLevels[] = $minCount;
$stepCounts = ($maxCount-$minCount)/$levels;
for ($i=0;$i<$levels;$i++) {
$fontLevels[] = (int)($minCount+=$stepCounts);
}
$fontsize = $fontSizes[0];
$result='';
foreach ($tagsCount as $tag => $count) {
for ($i=$levels;$i >= 0;$i--) {
if ($count >= $fontLevels[$i]) {
$fontsize = $fontSizes[$i];
$fontlevel = $i;
break;
}
}
$result.= $pdo->getChunk($tpl, array(
'fontlevel' => $fontlevel,
'tag' => $tag,
'fontsize' => $fontsize
));
}
return $result;P.S.: У сайта на скриншоте товары только добавляются, большинство тегов используются 1-3 раза, а те, что крупные, больше 20 раз.
P.P.S.: Наверняка, код можно написать покороче и лучше, но я совсем недавно начал работать на MODX. Буду рад вопросам и замечаниям :)
UPDATE 20.03.2018: Сниппет обновлён на корректный и добавлен pdoTools для обработки чанка.
Комментарии: 24
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
Евгений, собери пакет из этого? ;)
Да и компонент собрать не так уж сложно. На мой взгляд, конечно :)
Но я думаю пока рановато собирать пакет из одного сниппета :)
Это будет иметь смысл, когда понадобится больше функционала.
Например, выбор категорий, для которых нужно вывести теги, количество товаров рядом с тегом и что-то ещё.
Может даже можно будет приделать сферический 3D режим облака тегов.
Если будет спрос на это, то допишу и упакую в бесплатный пакет)
Тем более раз там 1 сниппет и чанк вывода тэгов, плюс для людей, которые не особо знакомы с MODX будет хорошо: кликнул — > установил -> вызвал -> profit.
чтобы не site.com/?tags=хоп%20%хей, а site.com/tags/hop-hei
С msearch2 просто обернул ссылкой
Где 68 — это страница каталоге, на который вызывается mFilter2 и прописан aliases: msoption|tags==tags.
Но можно сделать чтобы работало и по адресу /tags/[[+tag]] с помощью собственной маршрутизации.
Чанк:
Вывод товаров по тегу (нашел у Василия):
Подскажите, а как сделать несколько уровней, или остановить увеличение шрифта? Чем больше используется тег, тем больше шрифт. Спасибо!
Вопрос наверно не мне задан, но если будете использовать код из заметки, то там есть ограничение на максимальное число уровней)
Ваш код из заметки почему-то не работает. Возможно, вы выводите через mFilter2, а я вывожу без него. Вы не подскажите, как вывести товары через ваше облако тегов. Вывод товаров по тегу на странице не работает.Спасибо.
На странице вызова вывод товаров из последнего комментария. Может что не так делаю?
Не могу вывести товары по тегу, через PdoPage, со страницами. Просто когда один тег у сотни товаров, они выводятся все. Вы не подскажите, как вывести товары со страницами?
Вывод, конечно, не зависит от облака тегов.
Но стандартный вызов pdoPage должен решить проблему:
Но если сильно привязались к решению из комментария, то вместо этого:
напишите
и уже вызов этого сниппета вставьте в resources
Но я пытаюсь вывести на Fenom. Ничего не получается :( Наверное ошибаюсь в синтаксисе.
Я тоже могу ошибаться, например в optionFilter или ещё где-то :)
Вообщем решил так:
И вывод на странице:
Все работает.
Спасибо Вам за помощь!!!