Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rss Laravel Package

vinelab/rss

Vinelab RSS is a Laravel package for building and serving RSS feeds from your application. Define channels and items with a fluent API, manage feed metadata, and output valid RSS XML for readers and aggregators.

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require vinelab/rss

On Laravel 5.5+ the service provider is auto-discovered. On older apps (or if you're on a skeleton that disables discovery), register Vinelab\Rss\RssServiceProvider in config/app.php and optionally alias the facade:

'aliases' => [
    'Rss' => Vinelab\Rss\Facades\Rss::class,
],

First use case — fetch a feed and iterate articles:

use Vinelab\Rss\Facades\Rss;

$feed = Rss::feed('https://example.com/feed.xml');

$channel = $feed->channel();
echo $channel->title;

foreach ($feed->articles() as $article) {
    echo $article->title;
    echo $article->link;
    echo strip_tags($article->description);
}

Where to look first:

  • README.md — the canonical usage examples; the API surface is small.
  • src/Rss.php / src/Reader.php — the entry point and HTTP/XML fetch logic.
  • src/Feed.php — wraps a parsed feed; channel() and articles() live here.
  • src/Channel.php and src/Item.php — the value objects you'll actually render.
  • src/Facades/ and src/RssServiceProvider.php — container bindings if you need to swap or mock.

Start with a single feed in a tinker session (php artisan tinker) to confirm the upstream responds and that the fields you need (title, link, description, pubDate, author, guid) are populated.

Implementation Patterns

Wrap the facade behind a service. The facade is convenient but hard to fake precisely; inject a small FeedFetcher class that calls Rss::feed() internally. Your controllers/commands depend on the fetcher, and tests can swap it for a stub returning canned Feed objects.

Cache aggressively. Remote feeds are slow, rate-limited, and often return 304s you'd have to handle yourself. Wrap the call:

$feed = Cache::remember("rss:{$url}", now()->addMinutes(15), fn () => Rss::feed($url));

Cache the parsed result, not the raw XML, and key by URL. Invalidate on a schedule rather than per request.

Poll on a schedule, persist, dedupe. The typical production shape is a scheduled command:

// app/Console/Commands/ImportFeeds.php
foreach (config('feeds.sources') as $source) {
    $feed = Rss::feed($source);
    foreach ($feed->articles() as $article) {
        FeedItem::firstOrCreate(
            ['guid' => $article->guid ?? $article->link],
            [
                'title' => $article->title,
                'link' => $article->link,
                'summary' => strip_tags($article->description ?? ''),
                'published_at' => $article->pubDate ? Carbon::parse($article->pubDate) : null,
            ]
        );
    }
}

Register it with $schedule->command('feeds:import')->hourly(). This decouples user requests from upstream latency and gives you an audit trail.

Normalize into DTOs / API resources. Channel and Item expose loosely-typed properties (some are strings, pubDate may be an RFC-822 string or already parsed depending on version). Map them into your own value objects before exposing via API — this isolates the rest of the app from package quirks and makes it trivial to swap the library later.

Aggregate multiple sources. Loop over a config array of URLs, collect into a single collection, sort by published_at descending, and paginate. Do the fetching in a queued job per source so one slow feed doesn't block the rest; fan-in results via a cache or DB table.

Integrate with notifications. Combine with Laravel's notification system: after import, query newly created items and dispatch digests. Keep the RSS layer responsible only for fetching/parsing; business rules live in your domain code.

Gotchas and Tips

  • Maintenance status. Last release was March 2022. Pin the version explicitly in composer.json and add a smoke test that hits a known feed on CI. If PHP upgrades break the XML handling or a transitive dep, you'll want that failing fast.
  • HTTP behavior is opaque. The reader typically uses PHP's XML loading rather than a configured Guzzle client, so you get no timeout, user-agent, redirect, or TLS knobs out of the box. If upstream servers block the default agent or are slow, fetch the raw XML yourself (Http::timeout(10)->get($url)->body()) and feed it into the reader/parser if it supports a string input — otherwise proxy through your own cache.
  • Malformed XML. Real feeds contain BOMs, stray &, and bad entities. Wrap calls in try/catch (the package throws on parse failures; also check libxml_get_errors() if you debug). Sanitize by stripping the BOM and replacing bare ampersands before parsing if you control the fetch.
  • Character encoding. SimpleXML assumes UTF-8 unless the XML declaration says otherwise. Non-UTF-8 feeds produce mojibake; run mb_convert_encoding or ensure the declaration is intact.
  • pubDate is not a Carbon instance. RSS 2.0 uses RFC-822; always Carbon::parse($article->pubDate) and store in UTC. Don't rely on it being non-null — some feeds omit it.
  • HTML in description. Descriptions frequently contain CDATA-wrapped HTML. Escape on output ({{ }}) or strip_tags() on storage. Never render raw feed content directly — it's an XSS vector.
  • Namespaced extensions are invisible. media:content (images), dc:creator, content:encoded, iTunes tags, and Atom-specific fields aren't first-class in this package. If you need them, parse the raw XML separately with SimpleXMLElement and use children($ns), or use the package only for the common fields and augment elsewhere.
  • Atom vs RSS. This is an RSS client; Atom feeds may parse partially or not at all. Check $feed->channel() and articles() are non-empty; treat empty as a failure, not a valid empty feed.
  • Facade testing. Rss::shouldReceive(...) works, but the return types are concrete package classes. Easier to mock a thin wrapper interface than to build Feed/Item fixtures by hand — or construct them directly from a sample XML string.
  • Extension points. The service provider binds the reader; you can override the binding in a custom provider to plug in your own HTTP/parsing layer while keeping the Feed/Channel/Item API your app already uses. This is the cleanest escape hatch if you need modern features without a rewrite.
  • Debugging checklist. dd($feed->channel()) and dd($feed->articles()) first; if empty, dd(file_get_contents($url)) to confirm the response isn't an HTML error page or a 403. Enable libxml_use_internal_errors(true) around parsing in a scratch command to see the real failure.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle