При создании сайта на 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.
