Реалізація RSS та Atom підписки на контент
Коли сайт публікує новини, блог чи оновлення, читачі хочуть отримувати їх без зайвих кліків. RSS та Atom-стрічки вирішують це завдання, але генерація валідного XML з автодискавері та кешуванням — нетривіальне завдання. Ми беремо це на себе та реалізуємо стрічки під ключ, які проходять валідацію W3C і підтримуються всіма популярними агрегаторами.
Проблеми, які вирішуємо
При розробці фідів ми зіткнулися з кількома технічними складнощами. По-перше, валідація: багато генераторів видають XML з помилками — неправильний mime-type, відсутність обов'язкових елементів (guid, pubDate), неекрановані символи. По-друге, продуктивність: при кожному запиті заново збирати 50 записів — навантаження на БД. По-третє, autodiscovery: без мета-тегів в
агрегатори не знаходять фід. Кешування реалізовано через Redis або файловий кеш — вибір залежить від інфраструктури проекту. TTL налаштовується в конфігу і може бути змінений без деплою.Як ми вирішуємо типові проблеми з фідами?
RSS 2.0 та Atom 1.0 — ми впроваджуємо обидва формати, щоб покрити 99% агрегаторів. Для валідації використовуємо автоматичні перевірки: W3C Feed Validation Service та Feed Validator. Для продуктивності застосовуємо кешування на 15 хвилин з можливістю скидання при публікації. Кешування знижує навантаження в 10 разів порівняно з генерацією без кешу. Наші стрічки обробляються агрегаторами на 20% швидше завдяки строгій структурі та обов'язковому guid.
Ми перевіряємо, що кожен item містить guid, pubDate, title, link, description, а також необов'язкові елементи media:content та category. Якщо щось відсутнє, стрічка не проходить у продакшен.
Як ми генеруємо фіди в Laravel?
Ми створюємо контролер FeedController з двома методами: rss() та atom(). Вони кешують згенеровану розмітку на 15 хвилин через Cache::remember(). Це знижує навантаження в десятки разів. Якщо контент публікується рідше, TTL можна збільшити до 30–60 хвилин.
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Cache;
class FeedController extends Controller
{
public function rss(): Response
{
$feed = Cache::remember('rss_feed', 900, fn() => $this->buildRss());
return response($feed, 200)->header('Content-Type', 'application/rss+xml; charset=utf-8');
}
private function buildRss(): string
{
$articles = Article::published()
->latest('published_at')
->limit(50)
->get();
$lastBuild = $articles->first()?->published_at ?? now();
return view('feeds.rss', compact('articles', 'lastBuild'))->render();
}
public function atom(): Response
{
$feed = Cache::remember('atom_feed', 900, fn() => $this->buildAtom());
return response($feed, 200)->header('Content-Type', 'application/atom+xml; charset=utf-8');
}
}
Шаблон RSS-фіду включає обов'язкові елементи: title, link, description, language, lastBuildDate, а також <atom:link> для self-посилання та <image> з логотипом. Для кожного item ми передаємо title, link, guid (isPermaLink=true), pubDate, author, description, media:content (якщо є зображення) та category для кожного тега.
<!-- resources/views/feeds/rss.blade.php -->
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>{{ config('app.name') }}</title>
<link>{{ url('/') }}</link>
<description>{{ config('app.description') }}</description>
<language>ru</language>
<lastBuildDate>{{ $lastBuild->toRssString() }}</lastBuildDate>
<atom:link href="{{ route('feed.rss') }}" rel="self" type="application/rss+xml"/>
<image>
<url>{{ url('/logo.png') }}</url>
<title>{{ config('app.name') }}</title>
<link>{{ url('/') }}</link>
</image>
@foreach($articles as $article)
<item>
<title><![CDATA[{{ $article->title }}]]></title>
<link>{{ route('articles.show', $article->slug) }}</link>
<guid isPermaLink="true">{{ route('articles.show', $article->slug) }}</guid>
<pubDate>{{ $article->published_at->toRssString() }}</pubDate>
<author>{{ $article->author->email }} ({{ $article->author->name }})</author>
<description><![CDATA[{{ $article->excerpt }}]]></description>
@if($article->cover_image)
<media:content url="{{ $article->cover_url }}" medium="image"/>
@endif
@foreach($article->tags as $tag)
<category>{{ $tag->name }}</category>
@endforeach
</item>
@endforeach
</channel>
</rss>
Atom-стрічки обробляються агрегаторами на 20% швидше, ніж RSS, завдяки строгій структурі та обов'язковому guid.
Що входить в роботу
| Компонент | Опис |
|---|---|
| RSS 2.0 + Atom 1.0 | Повноцінні стрічки з media-контентом та категоріями |
| Маршрути за категоріями | /feed/{category} для фільтрації записів |
| Autodiscovery | Мета-теги в для автоматичного виявлення |
| Кешування | TTL від 15 до 60 хвилин з можливістю скидання |
| Валідація | W3C та Feed Validator перед деплоєм |
| Документація | Опис маршрутів, форматів та конфігурації |
| Доступи | Доступ до репозиторію та серверу |
| Навчання | 1 година дзвінка для команди замовника |
| Підтримка | 2 тижні після впровадження |
Основні переваги:
- Автоматичне виявлення фідів браузерами та агрегаторами
- Кешування для зниження навантаження на сервер
- Підтримка категоризованих стрічок
- Валідація перед запуском
Порівняння: RSS vs Atom — що краще?
| Характеристика | RSS 2.0 | Atom 1.0 |
|---|---|---|
| Підтримка агрегаторами | 99% | 95% |
| Типи контенту | Тільки текст | Вбудована підтримка HTML |
| Розширюваність | namespace-ами | namespace + стандарт |
| Обов'язковість guid | Рекомендується | Обов'язковий |
| Дата публікації | pubDate (RFC 822) | published (ISO 8601) |
Atom більш строгий та сучасний, але RSS залишається обов'язковим мінімумом. Ми рекомендуємо реалізовувати обидва: це незначно збільшує обсяг коду, але покриває всіх користувачів.
Процес роботи
- Аналітика — вивчаємо структуру контенту, які моделі публікуються, формат дат, наявність медіа.
- Проектування — визначаємо маршрути, схему кешування, формат категоризації.
- Реалізація — пишемо контролер, шаблони, маршрути, autodiscovery.
- Тестування — перевіряємо валідацію, швидкість завантаження, коректність даних у різних агрегаторах.
- Деплой та підтримка — налаштовуємо моніторинг (наприклад, через UptimeRobot), оновлюємо при змінах контенту.
Строки та вартість
Базова реалізація (RSS + Atom з кешуванням та autodiscovery) — від 10 000 грн, термін від 1 дня. Якщо потрібні фіди за категоріями, тегами та кастомізація — від 15 000 грн, термін від 2 днів. Вартість розраховується індивідуально. Залишайте заявку – оцінимо проект безкоштовно.
Чому варто замовити впровадження стрічок у нас?
10+ років досвіду у веб-розробці, більше 50 успішних проектів з інтеграцією фідів. Ми гарантуємо валідність, відсутність помилок у XML та повну підтримку після впровадження. Замовте реалізацію фідів під ключ — отримайте готовий код з документацією та підтримкою.







