Вывод RSS сайта через pdoResources
Честно говоря, я не очень люблю всякие рассылки и подписки, мне больше нравится использовать RSS.
Им очень удобно пользоваться — нужно просто зайти скопировать ссылку и вставить её в свой агрегатор новостей, например www.inoreader.com.
Для пущего удобства можно еще установить расширение для Chrome, чтобы вас регулярно уведомляли о свежих записях.
А теперь давайте посмотрим, как можно генерировать RSS с помощью pdoResources.
Давайте вначале сделаем ленту новостей со всеми тикетами сайта.
Для этого нам нужно создать новый ресурс с типом RSS, пустым шаблоном и желательно еще заморозить ему uri:
Я пишу пример для вывода заметок из Tickets, поэтому в условиях вызова pdoResources у меня вот это:
Поэтому пишем и указываем чанк tpl.Tickets.rss.row, в котором introtext будет проходить через фильтры вывода:
Как видите, здесь мы оборачиваем introtext в cdata, чтобы там нормально воспринимались теги, и прогоняем его через сниппет absUrl:
Теперь можно открывать вашсайт.ru/rss и проверять его на соответствие стандартам на сервисе validator.w3.org/feed/.
Осталось только добавить специальный тег в head страницы, чтобы уведомлять браузеры и расширения о том, что у вас есть RSS:
Предыдущий вариант RSS подойдёт для небольших сайтов и блогов, где заметок немного и их не нужно разделять по разделам.
Если же у вас сайт покрупнее, то лучше сделать возможность выбора разделов для генерации RSS.
Делается это просто: нужно заменить вызов pdoResources на свой сниппет, например rssFilter, с таким содержимым:
То есть, этот сниппет слушает $_GET['blogs'] и если там есть что-то подходящее, то фильтрует вывод тикетов по секциям и выставляет плейсхолдеры [[+title]] и [[+params]] на страницу с RSS.
Теперь меняем нашу страницу с выводом RSS (показываю только измененные куски, чтобы было понятнее):
Заголовок страницы:
Теперь можно еще сделать симпатичную страницу для генерации специальной ссылки только на определенные разделы, но это уже на ваше усмотрение.
Еще можно изменить вывод мета-тега RSS так, чтобы когда пользователь находится на странице раздела тикетов, он получал ссылку именно на этот раздел, а не на всё подряд:
Вот и всё, спасибо за внимание!
RSS — семейство XML-форматов, предназначенных для описания лент новостей, анонсов статей, изменений в блогах и т. п. Информация из различных источников, представленная в формате RSS, может быть собрана, обработана и представлена пользователю в удобном для него виде специальными программами-агрегаторами или онлайн-сервисами.
Им очень удобно пользоваться — нужно просто зайти скопировать ссылку и вставить её в свой агрегатор новостей, например www.inoreader.com.
Для пущего удобства можно еще установить расширение для Chrome, чтобы вас регулярно уведомляли о свежих записях.
А теперь давайте посмотрим, как можно генерировать RSS с помощью pdoResources.
Вывод всех заметок в ленту
Давайте вначале сделаем ленту новостей со всеми тикетами сайта.
Для этого нам нужно создать новый ресурс с типом RSS, пустым шаблоном и желательно еще заморозить ему uri:
Я пишу пример для вывода заметок из Tickets, поэтому в условиях вызова pdoResources у меня вот это:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>[[*pagetitle]] / [[++site_name]]</title>
<link>[[~[[*id]]?scheme=`full`]]</link>
<description>[[*description:cdata]]</description>
<language>en</language>
<copyright></copyright>
<ttl>120</ttl>
<atom:link href="[[~[[*id]]?scheme=`full`]]" rel="self" type="application/rss+xml" />
[[!pdoResources?
&tpl=`tpl.Tickets.rss.row`
&parents=`15`
&depth=`1`
&limit=`10`
&showHidden=`1`
&sortby=`createdon`
&where=`{"class_key":"Ticket"}`
&useWeblinkUrl=`1`
&scheme=`full`
]]
</channel>
</rss>
Для нормальной работы ленты необходимо, чтобы все ссылки на сайты и изображения были абсолютными — иначе RSS ридер не сможет их нормально отобразить.Поэтому пишем и указываем чанк tpl.Tickets.rss.row, в котором introtext будет проходить через фильтры вывода:
<item>
<title>[[+pagetitle]]</title>
<link>[[+link]]</link>
<description>[[+introtext:absURL:cdata]]</description>
<pubDate>[[+publishedon:date=`%a, %d %b %Y %H:%M:%S %z`]]</pubDate>
<guid>[[+link]]</guid>
</item>
Как видите, здесь мы оборачиваем introtext в cdata, чтобы там нормально воспринимались теги, и прогоняем его через сниппет absUrl:
<?php
if (empty($input)) {return false;}
$url = $modx->getOption('site_url');
preg_match_all('/(?:href|src)=[\'|"](.*?)[\'|"]/s', $input, $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $v) {
if (strpos($v, '://') === false) {
$input = str_replace($v, $url . ltrim($v, '/'), $input);
}
}
}
return $input;
Этот сниппет добавляет адрес сайта ко всем относительным ссылкам и картинкам, чтобы они нормально отображались в RSS ридере.Теперь можно открывать вашсайт.ru/rss и проверять его на соответствие стандартам на сервисе validator.w3.org/feed/.
Осталось только добавить специальный тег в head страницы, чтобы уведомлять браузеры и расширения о том, что у вас есть RSS:
<link href="[[++site_url]]rss" rel="alternate" type="application/rss+xml" title="RSS" />
Вместо id 10 укажите свой id с RSS страницей.Вывод ленты по разделам
Предыдущий вариант RSS подойдёт для небольших сайтов и блогов, где заметок немного и их не нужно разделять по разделам.
Если же у вас сайт покрупнее, то лучше сделать возможность выбора разделов для генерации RSS.
Делается это просто: нужно заменить вызов pdoResources на свой сниппет, например rssFilter, с таким содержимым:
<?php
// Инициализируем пустые переменные
$parents = $title = $alias = array();
// Слушаем переменную blogs
if (!empty($_GET['blogs'])) {
// Разбиваем список блоков
$blogs = array_map('trim', explode(',', $_GET['blogs']));
// Выбираем подходящие по alias секции
if (!empty($blogs)) {
$q = $modx->newQuery('TicketsSection', array('class_key' => 'TicketsSection', 'published' => 1, 'deleted' => 0));
$q->where(array('alias:IN' => $blogs));
$q->sortby('menuindex','ASC');
$q->select('id,pagetitle,alias');
if ($q->prepare() && $q->stmt->execute()) {
// Распихиваем результаты по переменным
while ($row = $q->stmt->fetch(PDO::FETCH_ASSOC)) {
$parents[] = $row['id'];
$title[] = $row['pagetitle'];
$alias[] = $row['alias'];
}
}
}
}
// Если были указаны конкретные секции - добавляем их в параметры вызова pdoResources
if (!empty($parents)) {
$scriptProperties['parents'] = implode(',', $parents);
$scriptProperties['depth'] = 0;
}
// Формируем более понятный заголовок
if (!empty($title)) {
$modx->setPlaceholder('title', implode(', ', $title));
}
else {
$modx->setPlaceholder('title', 'Все');
}
// И ссылку на эту ленту новостей
if (!empty($alias)) {
$modx->setPlaceholder('params', '?blogs='.implode(',',$alias));
}
// Вызываем pdoResources
return $modx->runSnippet('pdoResources', $scriptProperties);
То есть, этот сниппет слушает $_GET['blogs'] и если там есть что-то подходящее, то фильтрует вывод тикетов по секциям и выставляет плейсхолдеры [[+title]] и [[+params]] на страницу с RSS.
Теперь меняем нашу страницу с выводом RSS (показываю только измененные куски, чтобы было понятнее):
Заголовок страницы:
<title>[[!+title]] / [[++site_name]]</title>
Ссылки на ленту:<link>[[~[[*id]]?scheme=`full`]][[+params]]</link>
<atom:link href="[[~[[*id]]?scheme=`full`]][[+params]]" rel="self" type="application/rss+xml" />
Вызов сниппета:[[!rssFilter?
Вот, теперь сравните вывод всех заметок и только новостей.Теперь можно еще сделать симпатичную страницу для генерации специальной ссылки только на определенные разделы, но это уже на ваше усмотрение.
Еще можно изменить вывод мета-тега RSS так, чтобы когда пользователь находится на странице раздела тикетов, он получал ссылку именно на этот раздел, а не на всё подряд:
<link href="[[++site_url]]rss[[*class_key:is=`TicketsSection`:then=`?blogs=[[*alias]]`]]" rel="alternate" type="application/rss+xml" title="RSS" />
Вот и всё, спасибо за внимание!
Комментарии: 11
Как вывести дату по английски?
Решил проблему со сниппетом
snippet name: dateLocale
snippet name: dateLocale
<?php
setlocale(LC_ALL, 'en_US');
return strftime($options,$input);
Вывод[[+publishedon:dateLocale=`%a, %d %b %Y %H:%M:%S %z`]]
Делаю настройку по инструкции для простого блога (1 часть заметки). Всё сделал на написанному, только id свой указал. В итоге по адресу site.ru/rss получаю циклическую перезагрузку. Вообще не хочет отображать страницу с типом RSS. С чем это может быть связано? Подскажите кто знает.
У меня страница выходит вот такой — modzone.ru/rss/ то есть имеем в конце слеш. Возможно стоит [[Canonical]] в хеде (либо настройка в .htaccess), и устраивает войну с замороженным uri. Но это так из разряда предположений. Других вариантов я не вижу.
Точно. Виноват слэш. Спасибо.
П.С. Каноникал не делает редирект, он всего лишь прописывает url страницы. Но у меня его нет. :) Возможно в nginx правило такое настроено. Ещё раз спасибо.
П.С. Каноникал не делает редирект, он всего лишь прописывает url страницы. Но у меня его нет. :) Возможно в nginx правило такое настроено. Ещё раз спасибо.
Каноникал не делает редирект, он всего лишь прописывает url страницы.Буду знать)
Приветствую, вопрос про RSS, но немного отойдя от вопроса выше: Access-Control-Allow-Origin: *, как его запихнуть на RSS feed, если в структуре вывода фида участвует шаблонизатор пустого шаблона и если включаешь заголовок через шаблон, то фид просто не проходит валидацию?
Отвечаю на свой же вопрос по CORS, создаём сниппет с содержимым
<?php
header('Content-Type: application/rss+xml; charset=UTF-8');
header('Access-Control-Allow-Origin: *');
Перед выводом страницы вставляем то, чем обозвали[[!RSS-CORS]]<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>[[*pagetitle]] / [[++site_name]]</title>
<link>[[~[[*id]]?scheme=`full`]]</link>
<description>[[*description:cdata]]</description>
<language>ru</language>
<copyright></copyright>
<ttl>120</ttl>
<atom:link href="[[~[[*id]]?scheme=`full`]]" rel="self" type="application/rss+xml" />
[[!pdoResources?
&tpl=`tpl-rss`
&parents=`17`
&depth=`2`
&showHidden=`1`
&sortby=`createdon`
&includeContent=`1`
]]
</channel>
</rss>
Приветствую.
MODX Revolution 2.7.0-pl
Что-то ни первый вариант, ни второй у меня не сработал. Делал все по инструкции.
1. Создал ресурс с типом содержимого rss, пустым шаблоном и заморозил ему uri — rss, а также включил «Использовать текущий псевдоним в пути псевдонимов».
2. В поле «Содержимое» вставил код:
3. Создал чанк tpl.Tickets.rss.row с содержимым:
4. Создал сниппет absUrl с содержимым:
5. открываю ресурс mysite/rss и мне из динамического содержимого выводит только лишь title, link, description и atom:link.
Вот исходный код страницы, но это уже дает второй вариант (данной инструкции), который исходным кодом страницы незначительно отличается от первого:
Не пойму, почему не выводит остальное? В чем может быть причина?
P/S: В конце первого варианта написано:
MODX Revolution 2.7.0-pl
Что-то ни первый вариант, ни второй у меня не сработал. Делал все по инструкции.
1. Создал ресурс с типом содержимого rss, пустым шаблоном и заморозил ему uri — rss, а также включил «Использовать текущий псевдоним в пути псевдонимов».
2. В поле «Содержимое» вставил код:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>[[*pagetitle]] / [[++site_name]]</title>
<link>[[~[[*id]]?scheme=`full`]]</link>
<description>[[*description:cdata]]</description>
<language>en</language>
<copyright></copyright>
<ttl>120</ttl>
<atom:link href="[[~[[*id]]?scheme=`full`]]" rel="self" type="application/rss+xml" />
[[!pdoResources?
&tpl=`tpl.Tickets.rss.row`
&parents=`7`
&depth=`1`
&limit=`10`
&showHidden=`1`
&sortby=`createdon`
&where=`{"class_key":"Ticket"}`
&useWeblinkUrl=`1`
&scheme=`full`
]]
</channel>
</rss>
Вместо &parents=`15` прописывал свой id 7, пробовал 0 и др. id ресурсов-контейнеров.3. Создал чанк tpl.Tickets.rss.row с содержимым:
<item>
<title>[[+pagetitle]]</title>
<link>[[+link]]</link>
<description>[[+introtext:absURL:cdata]]</description>
<pubDate>[[+publishedon:date=`%a, %d %b %Y %H:%M:%S %z`]]</pubDate>
<guid>[[+link]]</guid>
</item>
4. Создал сниппет absUrl с содержимым:
<?php
if (empty($input)) {return false;}
$url = $modx->getOption('site_url');
preg_match_all('/(?:href|src)=[\'|"](.*?)[\'|"]/s', $input, $matches);
if (!empty($matches[1])) {
foreach ($matches[1] as $v) {
if (strpos($v, '://') === false) {
$input = str_replace($v, $url . ltrim($v, '/'), $input);
}
}
}
return $input;
5. открываю ресурс mysite/rss и мне из динамического содержимого выводит только лишь title, link, description и atom:link.
Вот исходный код страницы, но это уже дает второй вариант (данной инструкции), который исходным кодом страницы незначительно отличается от первого:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>Все / Название сайта</title>
<link>https://sitename.ru/rss</link>
<description><![CDATA[Мой rss канал]]></description>
<language>en</language>
<copyright></copyright>
<ttl>120</ttl>
<atom:link href="https://sitename.ru/rss" rel="self" type="application/rss+xml" />
</channel>
</rss>
Не пойму, почему не выводит остальное? В чем может быть причина?
P/S: В конце первого варианта написано:
Вместо id 10 укажите свой id с RSS страницей.Однако в примере id 10 нигде нет. Может я что-то упустил?
Да, pdoTools установлен, Tickets — установил перед использованием инструкции.
Вроде должно выводить, а не выводит.
Вроде должно выводить, а не выводит.
Ребята, 3й день бьюсь и не могу разобраться, почему у меня в rss дата стоит на всех новостях:
<pubDate>Thu, 01 Jan 1970 03:33:40 +0300</pubDate>
Создал сниппет:<?php
setlocale(LC_ALL, 'en_US');
return strftime($options,$input);
В tpl прописал: [[+publishedon:dateLocale=`%a, %d %b %Y %H:%M:%S %z`]]
Пробовал сниппет такой:<?php
setlocale(LC_ALL, 'en_US.UTF-8');
if ( $val == '' ) $val=time();
if ($format == '' ) $format = "%a, %d %b %Y %H:%M:%S";
return strftime($format, $val);
Всё равно на всех новостях дата 1970 год. Подскажите, как исправить?
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.