Решение: K2 получить материалы по тегу

  • 13 Ответов
  • 744 Просмотров

0 Пользователей и 1 Гость просматривают эту тему.

*

Оффлайн d0ublezer0

  • ****
  • 326
  • [+]29 / [-]0
  • Javaхарлал Неру
    • Просмотр профиля
мне была нужна такая функциональность: по определенному тегу выбрать все материалы из определенного раздела категорий со всеми вложенными категориями.
Такого решения я не нашел, более того, раз многие об этом спрашивают, но ответов нет, я понял, что решения готового тоже нет.
Написал сам. Делюсь.
Код: (php) [Выделить]
<?php
$GLOBALS
['db'] = JFactory::getDBO(); // получаем объект базы данных

JLoader::register('modK2ToolsHelper'JPATH_ROOT '/modules/mod_k2_tools/helper.php');  // подключаем помощника от модуля K2Tools
$GLOBALS['tag_cats'] = modK2ToolsHelper::getCategoryChildren(25); // собираем все дочерние для указанной категории материалов
$GLOBALS['tag_cats'] = @array_unique($GLOBALS['tag_cats']); // делаем список уникальным
$GLOBALS['tag_cats']=implode(",",$GLOBALS['tag_cats']); // склеиваем все категории 
JLoader::register('K2HelperRoute'JPATH_ROOT '/components/com_k2/helpers/route.php '); // подключаем роутер K2

function getItemsByTag($tags){
    
$tags=array_map('trim'explode(','$tags)); // разбираем теги на части и чистим их
    
$tags="'".implode("','",$tags)."'"// заново склеиваем теги для совместимости с MySQL

    
$query="SELECT #__k2_items.id, #__k2_items.title, #__k2_items.alias,#__k2_items.catid, #__k2_categories.alias AS cat_alias
    FROM (#__k2_tags INNER JOIN (#__k2_tags_xref LEFT JOIN #__k2_items ON #__k2_tags_xref.itemID = #__k2_items.id) ON #__k2_tags.id = #__k2_tags_xref.tagID) LEFT JOIN #__k2_categories ON #__k2_items.catid = #__k2_categories.id
    WHERE (((#__k2_tags.name) in (
$tags)) AND ((#__k2_items.catid) In (".$GLOBALS['tag_cats'].")) AND (#__k2_items.published = 1))";

    
$GLOBALS['db']->setQuery($query);  // выполняем запрос к базе
    
$items $GLOBALS['db']->loadAssocList("id"); // собираем объекты из ответа

    
if (count($items)>0){ // если результат не пустой
        
?>

        <ul class="fp-items-by-tag">
            <?
            foreach ($items as $item){ // для каждого материала создаем ссылку в списке
                $link = K2HelperRoute::getItemRoute($item["id"].':'.urlencode($item["alias"]), $item["catid"].':'.urlencode($item["cat_alias"]));
                ?><li><a href="<?=urldecode(JRoute::_($link));?>"><?=$item["title"]?></a></li><?  
            }

            ?>
        </ul>
        <?}
}
?>
Т.е. указав родительскую категорию, внутри которой нужно искать, мы можем вызывать функцию getItemsByTag("теги, по которым выполнять поиск, разделенные запятыми, или один тег")  - она выведет список со ссылками на материалы, соответствующие этому тегу.

Решение не претендует на уникальность и универсальность, но нужную мне задачу решает.

Может кому будет полезно..
« Последнее редактирование: 17.01.2016, 21:14:04 от d0ublezer0 »
Я помог вам? Ткните в карму.

*

Оффлайн benelli

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

*

Оффлайн benelli

Ап! Тема очень актуальна!

*

Оффлайн d0ublezer0

  • ****
  • 326
  • [+]29 / [-]0
  • Javaхарлал Неру
    • Просмотр профиля
Ап! Тема очень актуальна!
А готовое решение с комментариями из первого сообщения почему не подходит?
Я помог вам? Ткните в карму.

*

Оффлайн benelli

А готовое решение с комментариями из первого сообщения почему не подходит?
Я не понимаю куда этот код надо установить. И если верно понял, то надо прямо в коде указывать из каких категорий брать материалы и с какими тегами? Как быть если таких указаний на сайте надо сделать множество?

*

Оффлайн Septdir

А зачем такой геморой? Ну варианта 2.
Первый: Написать плагин( может займусь).
Второй: для нетерпиливых:

1. Заходите в файл /components/com_k2/models/itemlist.php
2.В нем находите 242 строку (пред ней повыше весть case: tag)
Код: (php) [Выделить]
JArrayHelper::toInteger($categories);
3. Добавляете перед этим одну строку
Код: (php) [Выделить]
$categories = $this->getCategoryTree($categories);Должно получится так
Код: (php) [Выделить]
if (is_array($categories))
{
$categories = $this->getCategoryTree($categories);
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
}

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

P.S Функция getCategoryTree позволяете получить древо категорий тоишь родителя которого вы указали и все вложенные категории. Она весьма полезна так что я ее частенько храню в хелпере
Не можете справиться с задачей сами пишите, решу ее за вас, не бесплатно*.
*Интересная задача, Деньги или Бартер. Натурой не беру!
________
Мои Контакты: Сайт | skype:septdir | Telegram | VK | Facebook | Twiter | Все контакты

*

Оффлайн benelli

А зачем такой геморой? Ну варианта 2.
Первый: Написать плагин( может займусь).
Второй: для нетерпиливых:

1. Заходите в файл /components/com_k2/models/itemlist.php
2.В нем находите 242 строку (пред ней повыше весть case: tag)
Код: (php) [Выделить]
JArrayHelper::toInteger($categories);
3. Добавляете перед этим одну строку
Код: (php) [Выделить]
$categories = $this->getCategoryTree($categories);Должно получится так
Код: (php) [Выделить]
if (is_array($categories))
{
$categories = $this->getCategoryTree($categories);
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
}

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

P.S Функция getCategoryTree позволяете получить древо категорий тоишь родителя которого вы указали и все вложенные категории. Она весьма полезна так что я ее частенько храню в хелпере
Не помогает это решение. Нет ни каких изменений по сравнению со стандартным отображением.
« Последнее редактирование: 11.09.2016, 23:37:14 от benelli »

*

Оффлайн Septdir

Не помогает это решение. Нет ни каких изменений по сравнению со стандартным отображением.
Значит не туда добавили ибо я проверил =). Там ниже еще есть когда категории строчное значение имеют. Ну да какие изменения должны быть, просто выводится все материалы и родителя и дочерней категории
Не можете справиться с задачей сами пишите, решу ее за вас, не бесплатно*.
*Интересная задача, Деньги или Бартер. Натурой не беру!
________
Мои Контакты: Сайт | skype:septdir | Telegram | VK | Facebook | Twiter | Все контакты

*

Оффлайн benelli

Значит не туда добавили ибо я проверил =). Там ниже еще есть когда категории строчное значение имеют. Ну да какие изменения должны быть, просто выводится все материалы и родителя и дочерней категории
А почему вы добавили изменения в itemlist ? Надо вывести материалы по тегу в другом материале, а не в списке материалов в категории.

*

Оффлайн Septdir

А почему вы добавили изменения в itemlist ? Надо вывести материалы по тегу в другом материале, а не в списке материалов в категории.
Ну потому что все списки получаются в model itemlist.php Тема была про то как получить список материалов, а не список материалов в самом материале. Хотя даже в самом материале список получаться там же просто функция другая
Фактически в этой функции другая логика и связки с категориями в принципе ибо связь идет сугубо то тэгам, но если хотите, сделать это не на много сложнее.
1. Заходите в файл /components/com_k2/models/itemlist.php
2.В нем находите функцию
Код: (php) [Выделить]
function getRelatedItems($itemID, $tags, $params)3. В функции находите строчку (955 строка примерно)
Код: (php) [Выделить]
$query .= " AND i.trash = 0
AND c.published = 1 ";
И пред ней добавляете
Код: (php) [Выделить]
$categories = $this->getCategoryTree($params->get('categories'));
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
Должно получиться так
Код: (php) [Выделить]
$categories = $this->getCategoryTree($params->get('categories'));
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
$query .= " AND i.trash = 0
AND c.published = 1 ";
Итого в материале при вызове ($this->relatedItems) вы будете получить массив материалов в которых содержаться данные тэги, а так же категории равна категории данного материала и всех вложенных. Но плагином такое не реализовать скорее всего, только кодом
Не можете справиться с задачей сами пишите, решу ее за вас, не бесплатно*.
*Интересная задача, Деньги или Бартер. Натурой не беру!
________
Мои Контакты: Сайт | skype:septdir | Telegram | VK | Facebook | Twiter | Все контакты

*

Оффлайн benelli

Ну потому что все списки получаются в model itemlist.php Тема была про то как получить список материалов, а не список материалов в самом материале. Хотя даже в самом материале список получаться там же просто функция другая
Фактически в этой функции другая логика и связки с категориями в принципе ибо связь идет сугубо то тэгам, но если хотите, сделать это не на много сложнее.
1. Заходите в файл /components/com_k2/models/itemlist.php
2.В нем находите функцию
Код: (php) [Выделить]
function getRelatedItems($itemID, $tags, $params)3. В функции находите строчку (955 строка примерно)
Код: (php) [Выделить]
$query .= " AND i.trash = 0
AND c.published = 1 ";
И пред ней добавляете
Код: (php) [Выделить]
$categories = $this->getCategoryTree($params->get('categories'));
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
Должно получиться так
Код: (php) [Выделить]
$categories = $this->getCategoryTree($params->get('categories'));
JArrayHelper::toInteger($categories);
$query .= " AND c.id IN(".implode(',', $categories).")";
$query .= " AND i.trash = 0
AND c.published = 1 ";
Итого в материале при вызове ($this->relatedItems) вы будете получить массив материалов в которых содержаться данные тэги, а так же категории равна категории данного материала и всех вложенных. Но плагином такое не реализовать скорее всего, только кодом
Получается вот такая фигня:
Ошибка: 1064
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') AND i.trash = 0 AND c.published = 1 AND c.access IN(1,1) AND c.trash =' at line 5 SQL=SELECT i.*, c.alias as categoryalias FROM #__k2_items as i LEFT JOIN #__k2_categories c ON c.id = i.catid WHERE i.published = 1 AND ( i.publish_up = '0000-00-00 00:00:00' OR i.publish_up <= '2016-09-12 14:47:23' ) AND ( i.publish_down = '0000-00-00 00:00:00' OR i.publish_down >= '2016-09-12 14:47:23' ) AND i.access IN(1,1) AND c.id IN() AND i.trash = 0 AND c.published = 1 AND c.access IN(1,1) AND c.trash = 0 AND (i.id) IN (96,50,311,309,94,310,93,46,349,316,498,384,385,317,318,315,367,95,522,47,312,348,386,499,521,270,528,527,387,45,313,369,526) ORDER BY i.created DESC LIMIT 0, 20

https://yadi.sk/i/3WWu2EHCv59XA

А плагин и не нужен, если это сделает код)
« Последнее редактирование: 12.09.2016, 19:57:37 от benelli »

*

Оффлайн benelli

ID сообщаются в ошибке как раз тех материалов, у которых есть нужный тег (при чем не только из требуемой категории, а из всех. Я проверил.)

*

Оффлайн Septdir

ID сообщаются в ошибке как раз тех материалов, у которых есть нужный тег (при чем не только из требуемой категории, а из всех. Я проверил.)
Включите отображение ошибок, в режим разработчик php и выложите текст ошибки. У вас не передается масиив с id категорий. Укажите версию движка, версию k2 ибо У Joomla 3.6.2 и k2 v 2.7.1 все норм.
закомоените строчку
Код: (php) [Выделить]
$query .= " AND c.id IN(".implode(',', $categories).")";И если включены ошибки и от они есть  то они вылезут.
Проверьте в каком месте не получаются id
Код: (php) [Выделить]
print_r($params->get('categories'));Или после JArrayHelper::toInteger($categories);
Код: (php) [Выделить]
print_r($categories);
« Последнее редактирование: 13.09.2016, 02:09:02 от Septdir »
Не можете справиться с задачей сами пишите, решу ее за вас, не бесплатно*.
*Интересная задача, Деньги или Бартер. Натурой не беру!
________
Мои Контакты: Сайт | skype:septdir | Telegram | VK | Facebook | Twiter | Все контакты

*

Оффлайн d0ublezer0

  • ****
  • 326
  • [+]29 / [-]0
  • Javaхарлал Неру
    • Просмотр профиля
P.S Функция getCategoryTree позволяете получить древо категорий тоишь родителя которого вы указали и все вложенные категории. Она весьма полезна так что я ее частенько храню в хелпере
Этот "геморрой", как вы выразились, вызван незнанием мной матчасти.
Естественно код с getCategoryTree гораздо удобнее, спасибо за наводку.
Я помог вам? Ткните в карму.