Схожі матеріали в Joomla

Код відображення 10 схожих публікацій в матеріалі Joomla!

При створенні сайту на CMS Joomla! можна використовувати модулі для відображення популярних матеріалів, останніх матеріалів, пов'язаних матеріалів, або новин із якоїсь однієї категорії. Як правило, цих модулів цілком достатньо для розробки простого сайту. Але іноді може виникнути потреба розширити функціональність веб-порталу, і тоді без внесення змін до коду CMS не обійтися.

Наприклад, ми знаємо, що модулі виводяться лише у певних позиціях шаблону сайту. Також їх можна відобразити у матеріалі. Але для цього потрібно опублікувати модуль в конкретному матеріалі. А ось можливості відобразити блок інформації автоматично в усіх статтях, або матеріалах з певної категорії - немає. І щоб вирішити подібну задачу, доведеться або редагувати кожен матеріал вручну, що є величезною тратою часу, або ж можна написати код, який додаватиме потрібну інформацію в зазначені статті.

Ось про це і буде наш сьогоднішній урок.

Відображення 10 схожих публікацій в Joomla

Перед нами стоїть завдання написати код, який виводитиме інформаційний блок під кожним матеріалом сайту. Назвемо цей блок - "Вас може зацікавити". Це пов'язано з тим, що у ньому виводитимуться посилання на схожі матеріали.

Принцип роботи цього блоку буде наступним:

  1. У блоці буде відображено не більше 10 посилань.
  2. До нього потраплятимуть останні 10 опублікованих матеріалів саме з тієї категорії, матеріал якої зараз переглядає користувач. Це цілком логічно. Адже якщо людина читає статтю про програмування на Javascript, то навряд чи її зацікавить матеріал про гру на гітарі чи вірші. Для SEO – це дуже хороший спосіб збільшити показник утримання. Адже, прочитавши одну статтю, людина може зацікавитися якимось із запропонованих варіантів і перейти до іншої статті за посиланням.
  3. Той матеріал, який зараз переглядає користувач у блок потрапляти не повинен. Це важливо для SEO. Не можна, щоб матеріал посилався сам на себе.
  4. Якщо в категорії лише один матеріал, то цілком логічно, що виводити блок схожих новин не потрібно. Адже користувач і так дивиться той єдиний матеріал, який опублікований в цій категорії.
  5. Якщо матеріал опублікований поза основною категорією, то в ньому не потрібно відображати схожі новини. Це пов'язано з тим, що поза основною категорією, ми можемо створити батьківські категорії в яких будуть допоміжні матеріали, а не інформаційні. Наприклад: контакти, мапа проїзду і т.д. Цілком логічно, що в таких матеріалах не потрібно виводити блок зі статтями.
  6. Посилання на матеріал має формуватися за наступною умовою: Якщо матеріал знаходиться в категорії, яка використовується пунктом меню, то в якості псевдоніма потрібно використовувати саме псевдонім пункту меню. Це також дуже важливо для SEO.

Підготовка файлу виведення новин на сайті

Перевірте, чи є у вас файли default.php і default_links.php за адресою /сайт/templates/шаблон/html/com_content/article/.

тут,

  • сайт – коренева папка вашого сайту;
  • шаблон – шаблон вашого сайту.

Код відображення інформаційного блоку

Описувати що робить цей код особливого сенсу немає. За коментарями в ньому, ви зможете зорієнтуватися, що і для чого написано.

Головне – правильно вставити цей код у потрібний файл.

Відкрийте файл /сайт/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>';
    }
}
?>

Якщо ж в налаштуваннях "Маршрутизації" (Система → Загальна конфігурація → Статті → Інтеграція) виставлена Застаріла Маршрутизація 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; ?>

Main Menu