Куда идем?

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

В данном уроке я расскажу о том, как вы можете быстро, самостоятельно, и абсолютно бесплатно сделать блок с похожими статьями под основным материалом, выведя в нем практически любую информацию. Для создания блока не используются сторонние расширения, только функционал Joomla «из коробки».

Как угодить всем?

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

Если вы автор всех материалов на сайте, или, по крайней мере, хорошо разбираетесь в тематике, то легко сможете подобрать статьи, которые могли бы дополнительно заинтересовать пользователя и при этом были бы релевантными по тематике. Давайте реализуем эту задумку.

Блок похожих статей Joomla. Шаг 1. Создаем дополнительное поле

Начиная с версии 3.7, в Joomla появились настраиваемые поля (Custom Fields). Используя их, мы можем добавлять к материалам отдельные блоки информации. К сожалению, среди доступных типов полей, нет поля «Похожие материалы Joomla», но зато есть поле SQL, которое мы и будем использовать.

На первом этапе наша задача сводится к тому, чтобы создать для материала дополнительное поле, позволяющее  привязывать к нему любые другие материалы. Для этого нам нужен множественный SELECT, опциями которого будут являться все материалы Joomla. Создать его очень легко.

1) Переходим в «Материалы –> Поля» и нажимаем кнопку «Создать»:

Перед вами откроется форма создания нового дополнительного поля. Заполняем ее следующим образом:

2

3

На вкладке «Основные» задаем:

  • Тип: SQL
  • Категория: Все
  • Имя: see-more
  • Название: на ваш выбор
  • Обязательно: Нет
  • Мультивыбор: Да
  • Запрос: SELECT id as value, title as text FROM #__content WHERE state = 1

На вкладке «Параметры» задаем:

  • Показать в: Оба
  • Автоматическое отображение: Не показывать автоматически

После этого сохраняем поле, и видим его в списке:

4

Если всё сделано правильно, то при создании новой статьи или при изменении существующей, вы увидите вкладку «Поля» на которой будет наше созданное поле с возможностью выбора любой опубликованной статьи с сайта.

5

В настройках поля мы использовали самый простой SQL-запрос, который выбирает все опубликованные материалы из базы данных. Если вы хотите каким-либо образом ограничить этот список, то подправьте запрос под себя, добавив, например, категории или даты публикации для фильтрации выбора. Хотя в Joomla удобно работать с полем SELECT даже с большим списком опций.

Если после создания дополнительного поля вы не видите его в форме редактирования материала, убедитесь, что:

1) У вас активирована опция: «Общие настройки –> Материалы –> Вкладка «Интеграция» –> Включить настраиваемые поля»

6

2) Плагины дополнительных полей активированы в менеджере плагинов.

3) Вы используете Joomla 3.7 или выше.

На этом первый шаг закончен. Поле выбора похожих материалов создано.

Блок похожих статей Joomla. Шаг 2. Вносим правки в макет материала

Теперь, когда у нас есть возможность выбора похожих материалов, нужно вывести их под текстом текущей статьи. Для этого нам нужно внести некоторые исправления в макет материала Joomla. Хаков не будет, т.к. этот макет переопределяется в шаблон Joomla.

Для переопределения макета материала, копируем файл:

/components/com_content/views/article/tmpl/default.php

в папку:

/templates/ВАШ_ШАБЛОН/html/com_content/article/

и вносим все дальнейшие изменения уже там.

В скопированном файле нам нужно внести следующие изменения:

1) Найдите строчку (~24):

JHtml::_('behavior.caption');

и вставьте после нее:

//------------------------------------------------------------------------------
//Получаем данные настраиваемых полей в удобном виде
foreach($this->item->jcfields as $jcfield)
	{
	  $this->item->jcFields[$jcfield->name] = $jcfield;
	}
//------------------------------------------------------------------------------

В принципе, эту строчку можно вставить в любом месте в начале файле после:

defined('_JEXEC') or die;

2) Найдите код:

<div itemprop="articleBody">
	<?php echo $this->item->text; ?>
</div>

и вставьте после него:

<?php //------------------------------------------------------------------------
if ($this->item->jcFields['see-more']->rawvalue) {
	$model = JModelLegacy::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
	$appParams = JFactory::getApplication()->getParams();
	$model->setState('params', $appParams);

	//Оставьте  в следующей строке только те поля, которые нужны вам для отображения похожих статей
	$model->setState('list.select', 'a.fulltext, a.id, a.title, a.alias, a.introtext, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by, a.publish_up, a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.featured');
	$access     = !JComponentHelper::getParams('com_content')->get('show_noauth');
	$authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
	$model->setState('filter.access', $authorised);
	//Подставляем ID материалов из дополнительного поля
	$model->setState('filter.article_id', $this->item->jcFields['see-more']->rawvalue);
	$seemore_items = $model->getItems();
	?>

<div class="related-articles">
	<h3>Смотрите также</h3>
	<ul>
	<?php foreach ($seemore_items as $seemore_item) { ?>
		<li>
			<a href="/<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($seemore_item->id,  $seemore_item->catid)); ?>"><?php echo $seemore_item->title ?></a>
		</li>
	<?php } ?>
	</ul>
</div>
<?php } //--------------------------------------------------------------------?>

Этот код получает материалы Joomla по их ID, которые, в свою очередь, мы берем из дополнительного поля, созданного на первом шаге. Далее материалы выводятся списком в блок похожих статей. Если вам сложно разобраться с кодом, начните, например, с видеоуроков html.

Статьи выводятся простым списком:

7

На самом деле, в  $seemore_item доступно очень много дополнительных данных по статьям, которые вы также можете вывести при желании. Вы можете оформить вывод похожих статей в виде таблице или блоков с картинками, добавить к ним даты, краткое описание, рейтинг и многие другие параметры.

Есть еще один вариант использования, аналогичный старому доброму плагину Extranews – показывать краткое описание похожих материалов, при наведении курсора на ссылку. Если хотите такой вариант, используйте код:

<?php //------------------------------------------------------------------------
if ($this->item->jcFields['see-more']->rawvalue) {
	$model = JModelLegacy::getInstance('Articles', 'ContentModel', array('ignore_request' => true));
	$appParams = JFactory::getApplication()->getParams();
	$model->setState('params', $appParams);

	//Оставьте  в следующей строке только те поля, которые нужны вам для отображения похожих статей
	$model->setState('list.select', 'a.fulltext, a.id, a.title, a.alias, a.introtext, a.state, a.catid, a.created, a.created_by, a.created_by_alias, a.modified, a.modified_by, a.publish_up, a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, a.hits, a.featured');
	$access     = !JComponentHelper::getParams('com_content')->get('show_noauth');
	$authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
	$model->setState('filter.access', $authorised);
	//Подставляем ID материалов из дополнительного поля
	$model->setState('filter.article_id', $this->item->jcFields['see-more']->rawvalue);
	$seemore_items = $model->getItems();

	JHTML::_('behavior.tooltip');
	?>

<div class="related-articles">
	<h3>Смотрите также</h3>
	<ul>
	<?php foreach ($seemore_items as $seemore_item) { ?>
		<li>
			<a class="hasTip" title="<?php echo htmlentities($seemore_item->title); ?>::<?php echo htmlentities($seemore_item->introtext); ?>" href="/<?php echo JRoute::_(ContentHelperRoute::getArticleRoute($seemore_item->id,  $seemore_item->catid)); ?>"><?php echo $seemore_item->title ?></a>
		</li>
	<?php } ?>
	</ul>
</div>
<?php } //--------------------------------------------------------------------?>

Результат, в этом случае, будет выглядеть так:

8

Дальнейшее оформление блока зависит только от вашей фантазии.

Блок похожих статей Joomla. Шаг 3. Добавляем похожие материалы и проверяем

Блок похожих материалов Joomla готов. Осталось только наполнить дополнительное поле релевантными статьями для разных материалов Joomla и они автоматически появятся на сайте в нашем блоке.

Поле выбора в Joomla сделано очень удобно и содержит в себе форму поиска по названию, позволяющую быстро ориентироваться даже в большом списке опций:

9

Вот и всё. Таким нехитрым способом мы реализовали дополнительный, очень полезный функционал, обойдясь встроенными инструментами Joomla, и не используя сторонних расширений.

Об авторе
Wedal
(Виталий). Веб-разработчик полного цикла (Full Stack). Создатель и автор сайта Wedal.ru.
Основной профиль – создание сайтов и расширений на CMS Joomla.
Добавить комментарий

Комментарии  
1
Спасибо за свеженькую статью. Только у меня этот блок вывелся вначале статьи, под заголовком, при чем обычным текстом, а не ссылками.
1
iygv, значит вы не отключили опцию "Автоматическое отображение" в настройках поля.
1
Пожалуйста, пишите впредь!
Даже если ваши заметки не являются необходимыми именно сейчас, они позволяют чувствовать ритм.
Спасибо!
1
Спасибо за отличную статью, Виталий!
Вопрос по теме: "как реализовать вывод такого поля для похожих статей, но не в под текстом текущей статьи, а например, после 5 абзаца?"
1
Александр, это немного сложнее. Прежде всего вам нужно точно понять, будут ли у вас в каждой статье абзацы (тег "p"), будет ли в каждой статье 5й абзац. Если ответы везде: ДА, то находим в макете статьи переменную, которая отвечает за вывод текста статьи, далее наша задача разбить ее на две части. В первую часть должны попасть только первые 5 тегов "p". Всё остальное во вторую часть. В результате у вас получится 2 новые переменные. Выводите первую, затем код блока похожих статей, затем вторую. Так решается задача.
Но вообще, это сомнительный вариант, как раз потому, что не всегда в тексте есть абзацы, оформленные тегом "p" и не всегда их 5 и больше. Вы можете также использовать маркер разбиения статьи на 2 части, который будете вставлять в материал самостоятельно, что-то вроде: {divide}. Далее делаете примерно так, как я писал в этом кейсе: https://wedal.ru/virtuemart-cases/kak-razdelit-opisanie-v-kategorii-virtuemart-2-3-na-do-i-posle-tovarov-kejs-6.html
1
Отличная статья, только так и не разобрался как выводить превью-картинку материала.
Делаю так , но выводит массив
Автомеханик{"image_intro":"images\/1.jpg","float_intro":"","image_intro_alt":"","image_intro_caption":"","image_fulltext":"images\/1.jpg","float_fulltext":"","image_fulltext_alt":"","image_fulltext_caption":""}

пробовал отсюда брать переменные, типа
ничего не выводит по ним. Подскажите, как нужно. Спасибо
1
Игорь, то, что у вас в фигурных скобках, это формат JSON. Он очень просто декодируется стандартной функцией PHP json_decode.

Посмотрите эту статью. В ней описан пример добавления изображений как раз из JSON:
https://wedal.ru/uroki-joomla/dobavlenie-izobrazhenij-v-standartnyj-modul-novostej-joomla.html
0
После

Код:

$seemore_items = $model->getItems();


Добавил

Код:

$image = json_decode($seemore_item->images, true);



После

Код:

<?php echo $seemore_item->title ?>


Добавил

Код:

<?php if($image) : ?> <img src= "<?php echo $image['image_intro'] ?>" alt="<?php echo $seemore_item->title ?>" /> <?php endif; ?>



но результата нет, ничего не выводится, что не так?
0
Игорь, после:

Код:

$image = json_decode($seemore_item->images, true);


Добавьте в html-секции:

Код:

<pre><?php print_r($image); ?></pre>


Там всё увидите.
0
Добавил, пусто, ничего не выводится
0
Игорь, значит в json_decode вы передаете что-то отличное от формата:
{"image_intro":"images\/1.jpg","float_intro":"","image_intro_alt":"","image_intro_caption":"","image_fulltext":"images\/1.jpg","float_fulltext":"","image_fulltext_alt":"","image_fulltext_caption":""}
0
Вот весь код, что не так?
0
Помогите пожалуйста добить уже, никак не выходит
0
Игорь, у вас переменная $image должена определяться в цикле foreach, а не перед ним.
0
Да, все получилось
Спасибо большое!
0
Еще проблема, если не загружена фотка к статье, то не скрывается попытка вывода изображения а выводится ошибка, иконка типа не найдено изображение
0
Игорь, да, всё верно. Просто оберните вывод изображения в PHP-условие проверки существования пути к изображению. Например, так:

Код:


<?php if ($image['image_intro']) { ?>
Выводим картинку
<?php } ?>

0
Виталий, а подскажите пожалуйста, как вывести дополнительные поля похожих статей?
0
Владислав, не совсем понял вопрос. В статье же про это и рассказывается. Или что вы имеете ввиду?
0
Виталий, в своей статье вы показываете, как сделать список похожих статей, состоящий из заголовков. Понятно, что аналогичным образом можно добавить картинки, описание и т.д. Меня же интересует как вывести в этом списке дополнительное поле, например с ценой, которое есть у похожих статей статей. Что бы каждая статья в этом списке была представлена заголовком, картинкой, описанием и ценой.
0
Владислав, хороший вопрос. Я сходу на него не отвечу.

Первым делом нужно проверить, а не загрузились ли уже данные настраиваемых полей в $seemore_items. Для этого поместите его в print_r
и посмотрите выведенные данные.

Если полей нет, то самым простым способом был бы SQL-запрос на их выбор из базы данных по ID материала. Но это не наш метод.
Правильный способ описан в этой из этих статей:
https://docs.joomla.org/J3.x:Adding_custom_fields/Implement_into_your_component
https://docs.joomla.org/J3.x:Adding_custom_fields/Overrides

Подробнее, к сожалению, не напишу - нужно тестировать.
0
Виталий, спасибо за подсказку. С Вашей помощью и по материалам форума, сделал такой вот код - выводим список похожих товаров с заголовком, картинкой, описанием и ценой.




Смотрите также
0
Владислав, подскажите, какой код вы написали, чтобы вывести дополнительные поля материала?
0
Сам сообразил.
В цикл foreach нужно добавить

Код:

$seemore_item->jcfields = FieldsHelper::getFields('com_content.article', $seemore_item, true);

0
Виталий, подскажите, а как можно изменить сортировку похожих статей? Сейчас статьи выводятся отсортированными по id, можно ли сделать сортировку по дате или наименованию ?
0
Владислав, да.

Добавьте перед:

Код:

$seemore_items = $model->getItems();



две строчки:

Код:

$ordering = $params->get('ordering', 'a.publish_up');
$model->setState('list.ordering', $ordering);

0
хм, что-то сортировка не срабатывает
0
Куда ЛАЙК ставить?))
0
Vetal, в отзывы =): https://wedal.ru/gb.html
0
У меня все не как у людей. Все сделал так как вы описали и вроде все получилось, список статей выводится внизу под основной статьей. но при нажатии на любую ссылку браузер пишет страница не найдена. и это естественно . ведь он пытается перейти по ссылке в которой часть адреса попросту отсутствует. Например переход должен быть по полному адресу http:// primer_ssilki.ru/blog/astra-110-1-spas-ot-gibeli-luchshij-bobinnik.html а переходит вот так /blog/astra-110-1-spas-ot-gibeli-luchshij-bobinnik.html . то есть адрес сайта во всех ссылках созданного блока отсутствует. что это может быть? В настройках самой joomla? Шаблон
Astroid Framework . Благодарю.
1
Сергей, нет, дело не в этом. Это просто относительная, а не абсолютная ссылка. Она также должна работать. Возможно у вас домен третьего уровня или такой страницы действительно не существует.
0

Цитирую Wedal:

Сергей, нет, дело не в этом. Это просто относительная, а не абсолютная ссылка. Она также должна работать. Возможно у вас домен третьего уровня или такой страницы действительно не существует.


Виталий, спасибо за ответ, буду искать. сейчас узнал, что в шаблоне было много изменений и переопределений и работают такие плагины как nodouble и тд. возможно причина где то рядом. Благодарю за полезную статью и ответ!
0
У меня тоже самое. Удалите начальный слеш из href ссылки и все заработает.
0
Спасибо за интересный материал, есть ряд вопросов.
1) Переменная $access вроде не используется в коде и зачем нужны эти две строчки, если без них все работает?

Код:

$authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
$model->setState('filter.access', $authorised);


2) Как эти поля вывести в модуле? Просто вставить в модуль HTML-кода не получается.
0
Виктор,

1) Да, вы правы. Эти две строчки, которые вы привели, должны выполняться внутри проверки на $authorised. Примерно вот так:


Код:

$access = !JComponentHelper::getParams('com_content')->get('show_noauth');
if ($access) {
$authorised = JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id'));
$model->setState('filter.access', $authorised);
}



2) В общем случае это некорректно. Поля относятся к материалам, а не к модулю. Теоретически, вы можете сделать модуль, в котором по ID будет определяться текущий открытый материал, а дальше для него будут загружаться поля. Но зачем такие сложности?
0
1) Я может что-то не понимаю, но без этих строчек показываются материалы в соответствии с уровнем доступа. Предназначенные для зарегистрированных не показываются гостям и т.д. Мне кажется они лишние.
2) Чтобы выводить их в боковой колонке, а не в статье. Есть способ сделать это без модуля?
0
Виктор,

1) Может быть сейчас так. Много времени прошло с момента публикации. Смотрите по результатам. Если вас устраивает результат без этой проверки, то ок.
2) В общем случае - нет. Все способы будут до некоторой степени велосипедами. Наверное, самым правильным способом будет написание своего специального модуля. Но это и самый сложный способ.
0
Крутая статья. Еще ближе к тому, чтобы перейти с К2 обратно на com_content. Но есть еще некоторые моменты, которые не позволяют этого сделать. Скажите, может быть есть решения в отношении того, как добавить аватар пользователю и организовать блог пользователя?
В каждой статье у меня имя автора и аватар со ссылкой на его блог. Плюс еще нужна возможность присваивать пункт меню для каждого блога. В к2 это все организовано из коробки. Но почему то в joomla этого нет. Может подскажете решение?
0
Ivan , для пользователя вы можете добавить аватар через дополнительные поля. Ссылки формировать под себя можно уже в альтернативных макетах. Если вы можете хотя бы немного писать и править код, то разберетесь с этим без проблем.
0
Скажите пожалуйста, а как сформировать запрос, чтобы в админке отображалась с заголовком материала еще и картинка ? В К2 я сделал так для удобства выбора похожих статей. То есть слева у меня изображение, справа заголовок статьи. Это удобно,!

Код:

SELECT id as value, title as text FROM #__content WHERE state = 1

- что нужно сюда добавить, чтобы в админке отображалась еще и изображение материала?
Спасибо!
0
Ivan, изображение материала (то, которое задается на вкладке Изображения и ссылки), хранится в поле атрибутов в базе данных (посмотрите точное название через PhpMyAdmin). Там оно хранится в формате JSON. Т.е. вы добавляете в запрос это поле, а после декодируете результат функцией json_decode. Так получите путь к изображению для материала.
Не забудьте переопределить макет, в котором будете добавлять картинку, в шаблон Joomla. Переопределение макетов работает и для шаблонов админки.
0
В отношении блога пользователя я похоже разобрался. Это можно сделать через компонент контакты. Поэтому решительно настроен избавиться от К2, толком обновлений там нет, а после каждого обновления переделывать функционал админ части у меня нет желания. Это и добавление описание тегов, и пакетное добавление тегов, и похожие материалы для статьи и еще куча всего. По сути ничего не меняется, только добавляет проблем. Установил новую версию К2 2.10.3. на чистую joomla, чтобы оценить изменения. Из нового это сайдбар интефейса, который некорректно отображается в админпанели поверх основной области просмотра и в том числе разъехавшиеся поля ввода. Так что все что нужно мне похоже уже есть в новой joomla из коробки!
0
Ivan, да, k2 сегодня уже не нужен. Почти все можно сделать на стандартный материалах Joomla, альтернативных макетах и настраиваемых полях.
0
Добрый день, статья огонь, но у меня проблема, в шаблоне нет папки /html/com_content/article/ и куда в таком случае вставлять default.php?
0
С тем вопросом отбой. вставил все работает, по прямому пути (по первому вашему пути)
0
Теперь другая проблема, все работает, но ссылки на похожие статьи делает как главный домен этой статьи (https:// адрес статьи) то есть нет того пути к статье который должен быть
0
Станислав, не понял. Напишите подробнее.
0
Должна быть ссылка с полным адресом а она получается доменной, как это исправить, спасибо?
0
Станислав, вообще в коде формируется относительная ссылка. Там не должно быть https. Атрибут ссылка href должен начинаться со слеша. В приведенном выше коде так и есть. Если по каким-то причинам у вас добавляется https, включите в коде в адрес ссылки название домена. Это, конечно, не очень правильно, но будет работать. Либо нужно разбираться откуда у вас берется https в адресе ссылки.
0
спасибо за ответ. А как сделать что бы ваша href ссылка выдавала полный путь?
0
Станислав, а зачем? Ну если очень хочется, добавьте перед ссылкой JURI::root()
0
Здравствуйте!
А есть описание как это сделать в Joomla 4.
Спасибо.
0
Владимир, примерно точно также. Единственное, код получения статей может немного отличаться. Если текущий код выдает ошибку, то откройте код модуля, например, последних материалов в Joomla 4 и сравните его с тем, что в статье. Легко можно будет найти изменения и поправить в соответствии с модулем.
0
Просто в 4-ке нет строки
JHtml::_('behavior.caption');
а при вставке в любое место кода:
//------------------------------------------------------------------------------
//Получаем данные настраиваемых полей в удобном виде
foreach($this->item->jcfields as $jcfield)
{
$this->item->jcFields[$jcfield->name] = $jcfield;
}
//------------------------------------------------------------------------------

страница не работает
0
Владимир, в Joomla 4 я не проверял.

JHtml::_('behavior.caption'); - в этой версии быть не должно.

Следующий код - включите в настройках Joomla отображение ошибок и посмотрите, какая ошибка появляется.
0
Оказывается первый код, без tooltip, работает. Только ссылку на связанные статьи строит неправильно, исключает название сайта ссылки, соответственно не может открыть связанную статью.