Реалізація 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 та повну підтримку після впровадження. Замовте реалізацію фідів під ключ — отримайте готовий код з документацією та підтримкою.







