При створенні сайту на CMS Joomla! можна використовувати модулі для відображення популярних матеріалів, останніх матеріалів, пов'язаних матеріалів, або новин із якоїсь однієї категорії. Як правило, цих модулів цілком достатньо для розробки простого сайту. Але іноді може виникнути потреба розширити функціональність веб-порталу, і тоді без внесення змін до коду CMS не обійтися.
Наприклад, ми знаємо, що модулі виводяться лише у певних позиціях шаблону сайту. Також їх можна відобразити у матеріалі. Але для цього потрібно опублікувати модуль в конкретному матеріалі. А ось можливості відобразити блок інформації автоматично в усіх статтях, або матеріалах з певної категорії - немає. І щоб вирішити подібну задачу, доведеться або редагувати кожен матеріал вручну, що є величезною тратою часу, або ж можна написати код, який додаватиме потрібну інформацію в зазначені статті.
Ось про це і буде наш сьогоднішній урок.
Відображення 10 схожих публікацій в Joomla
Перед нами стоїть завдання написати код, який виводитиме інформаційний блок під кожним матеріалом сайту. Назвемо цей блок - "Вас може зацікавити". Це пов'язано з тим, що у ньому виводитимуться посилання на схожі матеріали.
Принцип роботи цього блоку буде наступним:
- У блоці буде відображено не більше 10 посилань.
- До нього потраплятимуть останні 10 опублікованих матеріалів саме з тієї категорії, матеріал якої зараз переглядає користувач. Це цілком логічно. Адже якщо людина читає статтю про програмування на Javascript, то навряд чи її зацікавить матеріал про гру на гітарі чи вірші. Для SEO – це дуже хороший спосіб збільшити показник утримання. Адже, прочитавши одну статтю, людина може зацікавитися якимось із запропонованих варіантів і перейти до іншої статті за посиланням.
- Той матеріал, який зараз переглядає користувач у блок потрапляти не повинен. Це важливо для SEO. Не можна, щоб матеріал посилався сам на себе.
- Якщо в категорії лише один матеріал, то цілком логічно, що виводити блок схожих новин не потрібно. Адже користувач і так дивиться той єдиний матеріал, який опублікований в цій категорії.
- Якщо матеріал опублікований поза основною категорією, то в ньому не потрібно відображати схожі новини. Це пов'язано з тим, що поза основною категорією, ми можемо створити батьківські категорії в яких будуть допоміжні матеріали, а не інформаційні. Наприклад: контакти, мапа проїзду і т.д. Цілком логічно, що в таких матеріалах не потрібно виводити блок зі статтями.
- Посилання на матеріал має формуватися за наступною умовою: Якщо матеріал знаходиться в категорії, яка використовується пунктом меню, то в якості псевдоніма потрібно використовувати саме псевдонім пункту меню. Це також дуже важливо для SEO.
Підготовка файлу виведення новин на сайті
Перевірте, чи є у вас файли default.php і default_links.php за адресою /сайт/templates/шаблон/html/com_content/article/.
тут,
- сайт – коренева папка вашого сайту;
- шаблон – шаблон вашого сайту.
Примітка.
Якщо в каталозі html немає папки com_content, то її потрібно створити.
Якщо в каталозі com_content немає папки article, то її потрібно створити.
Якщо в каталозі article відсутні файли default.php та default_links.php, то їх потрібно скопіювати звідси. /сайт/components/com_content/tmpl/article/.
Пояснення.
За відображення повного матеріалу на сайті відповідає файл /сайт/components/com_content/tmpl/article/default.php. Ми копіюємо його в папку /сайт/templates/шаблон/html/com_content/article/ для того, щоб під час оновлення CMS Joomla! він не був перезаписаний.
Файли, які знаходяться в каталозі /сайт/templates/шаблон/html/ не перезаписуються під час оновлення CMS Joomla!
Відповідно, якщо ми внесемо зміни до файлу за шляхом /сайт/components/com_content/tmpl/article/default.php то при наступному оновленні CMS, він може бути замінений на новий файл, і тоді все що ви зробили пропаде.
А от файл за адресою /сайт/templates/шаблон/html/com_content/article/default.php не буде перезаписаний ніколи.
Важнливо!
Копіювати потрібно два файли: default.php і default_links.php.
Код відображення інформаційного блоку
Описувати що робить цей код особливого сенсу немає. За коментарями в ньому, ви зможете зорієнтуватися, що і для чого написано.
Головне – правильно вставити цей код у потрібний файл.
Відкрийте файл /сайт/templates/шаблон/html/com_content/article/default і впишіть в нього наступний код.
<?php
// Відображення блоку "Вас може зацікавити"
// Отримуємо об'єкт поточної сторінки
$app = Joomla\CMS\Factory::getApplication();
$menu = $app->getMenu();
$active = $menu->getActive();
// Отримуємо ID категорії поточної сторінки
$category_id = $active->query['id'];
// Отримуємо пункт меню, яке використовує цю категорію
$menuItems = $menu->getItems('component', 'com_content');
foreach ($menuItems as $menuItem) {
if ($menuItem->query['id'] == $category_id) {
// Перевіряємо рівень вкладеності пункта меню
if ($menuItem->level >= 3) {
// Отримуємо батьківський пункт меню
$parentMenuItem = $menu->getItem($menuItem->parent_id);
// Перевіряємо, чи використовується батьківський пункт меню
$rootMenuItem = $parentMenuItem->parent_id != 0 ? $menu->getItem($parentMenuItem->tree[0]) : $parentMenuItem;
// Формуємо посилання
$menuAlias = $rootMenuItem->alias . '/' . $menuItem->alias;
} else {
// Формуємо посилання
$menuAlias = $menuItem->alias;
}
break;
}
}
// Визначаємо псевдонім батьківської категорії, якщо є
if ($category->parent_id != 0) {
$parentCategory = JCategories::getInstance('Content')->get($category->parent_id);
$parentAlias = $parentCategory->alias;
$menuAlias = $parentAlias . '/' . $menuAlias;
}
// Формуємо підсумкове посилання
$linkMenuAlias = JRoute::_('index.php?option=com_content&view=article&id=' . $article->id . '&catid=' . $category_id . ':' . $category->alias . '&Itemid=' . $menuItem->id);
// Вставляємо псевдонім в посилання
$linkMenuAlias = str_replace($category->alias, $menuAlias, $linkMenuAlias);
// Додаємо псевдонім кореневого пункту меню, якщо потрібно
if (isset($rootMenuItem) && $rootMenuItem->level >= 3) {
$rootAlias = $menu->getItem($rootMenuItem->tree[0])->alias;
$linkMenuAlias = '/' . $rootAlias . $linkMenuAlias;
}
// Виводимо останні 10 публікацій із зазначеної категорії
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$currentDate = JFactory::getDate()->toSql();
$query->select('a.id, a.title, a.alias, a.introtext, c1.alias AS sub_category_alias, c2.alias AS category_alias, c3.alias AS parent_alias');
$query->from($db->quoteName('#__content', 'a'));
$query->leftJoin($db->quoteName('#__categories', 'c1') . ' ON c1.id = a.catid');
$query->leftJoin($db->quoteName('#__categories', 'c2') . ' ON c2.id = c1.parent_id');
$query->leftJoin($db->quoteName('#__categories', 'c3') . ' ON c3.id = c2.parent_id');
if (!empty($category_id)) {
$query->where('a.catid = ' . (int)$category_id);
} else {
$query->where('a.catid > 0');
}
$query->where('a.state = 1');
$query->where('c1.published = 1');
$query->where('c1.access IN (' . implode(',', JFactory::getUser()->getAuthorisedViewLevels()) . ')');
$query->where('(a.publish_up = ' . $db->quote('0000-00-00 00:00:00') . ' OR a.publish_up <= ' . $db->quote($currentDate) . ')');
$publishDownClause = '(a.publish_down = ' . $db->quote('0000-00-00 00:00:00') . ' OR a.publish_down >= ' . $db->quote($currentDate) . ')';
$query->where('(' . $publishDownClause . ' OR a.publish_down IS NULL)');
$query->order('a.publish_up DESC');
$query->setLimit('10');
$db->setQuery($query);
$results = $db->loadObjectList();
if (!empty($results)) {
// перевіряємо, чи кількість посилань більша за 1
if (count($results) > 1) {
echo '<div class="alert alert-grey" role="alert"><h2 class="float-center">' . JText::_('COM_CONTENT_LAST_PUBLISHED') . '</h2>';
echo '<ul>';
foreach ($results as $result) {
$url = '';
if (!empty($linkMenuAlias)) {
$url .= $linkMenuAlias;
} elseif (!empty($result->parent_alias)) {
$url .= '/' . $result->parent_alias;
}
$url .= '/' . $result->alias;
// Пропускаємо матеріал, що відповідає поточній сторінці
$currentUrl = JUri::getInstance()->toString();
$urlWithoutDomain = substr($url, strlen(JUri::root()));
if (strpos($currentUrl, $urlWithoutDomain) !== false || JUri::getInstance()->getPath() === $urlWithoutDomain) {
continue;
}
//Виводимо підсумкове посилання
echo '<li><a href="' . $url . '">' . $result->title . '</a></li>';
}
echo '</ul></div>';
}
}
?>
Примітка.
Код працює за наявності не більше 3 підпунктів меню. Тобто, посилання на матеріал може мати такий вигляд:
- Головна/Категорія1/Матеріал
- Головна/Категорія 1/Категорія 2/Матеріал
- Головна/Категорія 1/Категорія 2/Категорія 3/Матеріал
Якщо рівень підпунктів меню більший ніж 3, то потрібно трохи підправити код.
Важливо!
Посилання будуть формуватися правильно лише за умови, що в налаштуваннях "Маршрутизації" (Система → Загальна конфігурація → Статті → Інтеграція) виставлена Сучасна Маршрутизація URL.
Якщо ж в налаштуваннях "Маршрутизації" (Система → Загальна конфігурація → Статті → Інтеграція) виставлена Застаріла Маршрутизація URL, то потрібно замінити цей фрагмент коду.
foreach ($results as $result) {
$url = '';
if (!empty($linkMenuAlias)) {
$url .= $linkMenuAlias;
} elseif (!empty($result->parent_alias)) {
$url .= '/' . $result->parent_alias;
}
$url .= '/' . $result->alias;
на
foreach ($results as $result) {
$url = '';
if (!empty($linkMenuAlias)) {
$url .= '/' . $linkMenuAlias;
} elseif (!empty($result->parent_alias)) {
$url .= '/' . $result->parent_alias;
}
$url .= '/' . $result->alias;
if (!empty($result->id)) {
$url = str_replace('-/', '' . $result->id . '-', $url);
}
$url = '/' . trim($url, '/');
Куди вставляти код?
Особисто я вставив код в фал default.php в самому низу після:
<?php echo LayoutHelper::render('joomla.content.readmore', ['item' => $this->item, 'params' => $params, 'link' => $link]); ?>
<?php endif; ?>
<?php endif; ?>
І перед:
<?php
if (!empty($this->item->pagination) && $this->item->paginationposition && $this->item->paginationrelative) :
echo $this->item->pagination;
?>
<?php endif; ?>
<?php // Content is generated by content plugin event "onContentAfterDisplay" ?>
<?php echo $this->item->event->afterDisplayContent; ?>
Примітка.
Цей код тестувався на CMS Joomla! версії 3.10.11 та 4.2.9.