MODX - Как вывести популярные статьи
Урок, на котором рассмотрим, как с помощью сниппетов pdoTools создать виджет, отображающий на сайте 5 самых популярных статей за последние 7 дней.
Описание виджета "Популярные статьи"
Виджет "Популярные статьи" предназначен для отображения на сайте 5 самых просматриваемых страниц за последние 7 дней.

Визуально данный виджет выполним в виде панели (компонента panel) front-end фреймворка Twitter Bootstrap. Содержимое панели организуем в виде нумерованного списка статей в порядке их убывания по количеству просмотров за неделю.
Необходимые компоненты
Рассматривать создание блока "Самое популярное" будем для сайта, в котором статьи организованы на базе компонента Tickets. По умолчанию просмотры тикетов в компоненте Tickets ведутся только для зарегистрированных пользователей. Для того чтобы просмотры регистрировались и для незарегистрированных посетителей, необходимо включить опцию "tickets.count_guests" в настройках.

Кроме компонента Tickets, потребуется ещё компонент pdoTools. Данный компонент, содержит хороший набор сниппетов. В этой статье будем использовать из этого набора только сниппет pdoResources.
Таблицы TicketView и Ticket
Для создания запросов понадобятся 2 таблицы: TicketView и Ticket.
Первая таблица (TicketView) содержит записи о просмотренных пользователями тикетах. Она состоит из четырёх полей, но для выполнения запроса понадобятся только 2. Первое поле - это parent
, оно хранит id
просмотренного пользователем тикета. Второе поле - это timestamp
, оно предназначено для хранения даты просмотра.
Вторая таблица (Ticket) будет основной. Она понадобится для того чтобы выбрать из неё необходимые ресурсы для которых будем подсчитывать количество просмотров.
Взаимосвязь между таблицами представим на следующей схеме:

Разработка виджета "Популярные статьи"
Создание виджета осуществим за 2 шага:
- Напишем сниппет getDateWeekAgo, который будет возвращать дату, которая была 7 дней назад.
- Выберем и выведем необходимые ресурсы с помощью сниппета pdoResources и getTicket. Сравним время и ресурсы, затрачиваемые ими на обработку.
Создание сниппета getDateWeekAgo
Для создания сниппетов необходимо открыть в левой панели администрирования вкладку "Элементы" и нажать на значок "+" напротив надписи "Сниппеты". В открывшейся странице ввести следующее:
- в поле "Имя": getDateWeekAgo.
- в поле "Код сниппета" следующий код:
<?php $formatDate = date('Y-m-d H:i:s'); $date = new DateTime($formatDate); $date->modify("-7 day"); return $date->format('Y-m-d H:i:s');

Выборка записей с помощью сниппета pdoResources
В качестве 1 способа выберем и выведем записи с помощью сниппета pdoResources. Для этого необходимо открыть нужный шаблон или чанк, и поместить в него следующий код:
<section class="panel panel-danger"> <div class="panel-heading"> <h5 class="panel-title"> <i class="fa fa-heart"></i> <span title="Самые популярные статьи и уроки за последние 7 дней">Популярные статьи</span> </h5> </div> <div class="panel-body"> [[!pdoResources? &loadModels=`tickets` &class=`Ticket` &leftJoin=`{ "TicketView": { "class": "TicketView", "on": "Ticket.id = TicketView.parent" } }` &parents=`4` &where=`{"TicketView.timestamp:>":"[[!getDateWeekAgo]]"}` &select=`{ "Ticket": "Ticket.id as id, Ticket.uri as uri, Ticket.pageTitle as pagetitle", "TicketView": "COUNT(TicketView.parent) as countviews" }` &hideContainers=`1` &groupby=`Ticket.id` &sortby=`{"countviews":"desc"}` &tpl=`@INLINE <p><span class="badge" style="background-color:#cc2929">[[+idx]]</span> <a href="[[+uri]]" style="color: #cc2929; vertical-align: middle;">[[+pagetitle]]</a> <span style="color: #cc2929;"><i class="fa fa-eye" style="vertical-align: middle;"></i><span style="vertical-align: middle;" title="Количество просмотров за последние 7 дней"> [[+countviews]]</span></span></p>` &limit=`5` ]] </div> </section>

Выборка записей с помощью сниппета getTickets
В качестве 2 способа рассмотрим выборку данных и их отображение с помощью сниппета getTickets.
<section class="panel panel-danger"> <div class="panel-heading"> <h5 class="panel-title"> <i class="fa fa-heart"></i> <span title="Самые популярные статьи и уроки за последние 7 дней">Популярные статьи</span> </h5> </div> <div class="panel-body"> [[!getTickets? &leftJoin=`{ "TicketView": { "class": "TicketView", "on": "Ticket.id = TicketView.parent" } }` &parents=`4` &where=`{"TicketView.timestamp:>":"[[!getDateWeekAgo]]"}` &select=`{ "Ticket": "Ticket.id as id, Ticket.uri as uri, Ticket.pageTitle as pagetitle", "TicketView": "COUNT(TicketView.parent) as countviews" }` &hideContainers=`1` &groupby=`Ticket.id` &sortby=`{"countviews":"desc"}` &tpl=`@INLINE <p><span class="badge" style="background-color:#cc2929">[[+idx]]</span> <a href="[[+uri]]" style="color: #cc2929; vertical-align: middle;">[[+pagetitle]]</a> <span style="color: #cc2929;"><i class="fa fa-eye" style="vertical-align: middle;"></i><span style="vertical-align: middle;" title="Количество просмотров за последние 7 дней"> [[+countviews]]</span></span></p>` &limit=`5` ]] </div> </section>

&parent
. Т.е. для того чтобы настроить виджет "Популярные статьи" на свой сайт, Вам достаточно изменить значение 4 на необходимое.Сравнение результатов работы сниппетов
Как видно из результатов логов, сниппет pdoResources выбирает данные намного быстрее. Это связано с тем, что в запросе участвуют только нужные таблицы. В то время как сниппет getTickets дополнительно подключает ещё классы (таблицы) TicketsSection, modUser и modUserProfile.
можете пожалуйста подсказать как вывести счетчик просмотров не за неделю а за все время?
Просто удалите из вызова сниппета параметр &where.
Не работает. На сайте пишет «Array». В логах пишет ошибку:
Подскажите, как грамотно сделать запрос.
Для вывода лога можно использовать параметр:
Но не работает
Поставил пишет:
Почитал статью про xpdo:
https://bezumkin.ru/training/course2/3006/
Повставлял разные варианты, но безуспешно.
Если вызывать так:
То картинки отображаются.
Но в таком вызове выводятся тикеты свежие, а мне как у вас популярные нужны.
В итоге рабочий вызов:
Шеф, спасибо за наводку!
В шаблоне: И чанк:
2. В чанке в необходимое место добавить следующий плейсхолдер:
Т.е. с помощью pdoResources выводим необходимый список страниц. После выбора необходимой страницы и нажатию на кнопку, запускаем ajax-запрос на сервер, который передаёт php скрипту ([[!ajaxpage]]), расположенному на этой же странице, id ресурса, который мы хотим получить. После получения выводим его в блок, имеющий id=«id1».
php скрипт [[!ajaxpage]] — это сниппет с именем ajaxpage, который возвращает контент ресурса по его id.
Код сниппета ajaxpage будет следующим:
Сделал как у вас — все работает, спасибо.
Но вот такая проблема (с данной статьей не совсем связанная), — количество просмотров, как будто закешировалось (вывожу [[+views]]. После просмотра новых тикетов показывается (после перезагрузки страницы) один просмотр, последующие визиты на счетчике не отражаются. В настройках tickets «Считать просмотры страниц гостями — да». Количество комментариев отображается корректно, а просмотры не считает.
Подскажите в чем причина.
Так же сниппет который извлекает данные из базы должен быть вызван не кэшированным:
Делаю так
Чанк tpl.post
В выводе не отображаются countviews и изображения. Спасибо
У меня в примере не было категорий, поэтому этот момент упустил.
Для этого у тебя есть такие посетители как Я)))
Рад помочь хорошему человеку! Благодаря твоему блогу, Я прогрессирую в изучении Модэкса, чему очень рад. Находя такие мелкие недочёты, Я вижу, что Я развиваюсь)
Таблицу TicketView нашел в бд, а вот вторую таблицу Ticket, которая основная, не могу найти. Откуда вообще такие названия, если в бд они по другому называются? А то не пойму как работают leftJoin и select с такими названиями таблиц)
Для компонента Tickets они берутся из файла tickets.mysql.schema.xml.
Он находится в каталоге /core/components/tickets/model/schema.
Если его открыть, то будет видно, что данный класс — это расширение modResource.
А modResource — это уже стандартный класс MODX. Он берётся уже из файла modx.mysql.schema.xml. Он находится в каталоге /core/model/schema.
В этом файле видно что с классом modResource связана таблица site_content.
В итоге класс Ticket — это таблица site_content. В статье описано более просто, для того чтобы не вдаваться в подробности. Чтобы было более понятно начинающему разработчику. Т.е. таблица TicketView — просмотры, Ticket — тикеты.
Урока по созданию слайдера с использованием FlexSlider, например, стоит ожидать?)
Есть вопрос. Заметила, что у modx revo картинки индексируются как отдельная страница.
Это как то влияет на продвижение в поисковиках? Ведь общее количество загруженных страниц получается явно больше, за счет индексации изображений. Есть ли санкции у писковиков для modx за это?))
Что-то новенькое )
У меня количество страниц равно количеству загруженных страниц.
А если нужны вообще популярные, а не за последние 7 дней. То просто делать без сниппета и из кода убрать
?
А зачем спрашиваешь? Если ты сам ответил на свой вопрос.
Два вопроса не по теме)
Ты вообще никаким редактором в админке не пользуешься?
Водяные знаки к картинкам делаешь в каком-то онлайн сервисе или как-то в модексе это дело автоматизировал?
Картинки делаю в GIMP, а именно их обрезку, настройку (если необходимо), наложение водяных знаков и сжатие. Там всё это делается за несколько кликов. В автоматизации данного процесса с помощью php не вижу смысла, т.к. не делаю больше 10 картинок в неделю.