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

Laravel Feeds Laravel Package

dragon-code/laravel-feeds

dragon-code/laravel-feeds is a lightweight Laravel package for generating RSS and Atom feeds from your application data. Define channels and items with a simple API, customize feed metadata, and serve standards-compliant XML to readers and aggregators without hand-writing feed markup.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Know what it does. This package generates feed files — XML, CSV, JSON — from large datasets. It is an export tool for marketplaces and ad systems, not a feed reader or a crawler.
  • Check your runtime before you install anything. 2.x moves the floor to PHP 8.4, Laravel 13, and Pest 5 (#297, marked build! — a breaking build change). If you are not on that stack yet, install ^1.0 and plan the jump separately. Do not half-upgrade.
  • Install: composer require dragon-code/laravel-feeds. Laravel package discovery registers the provider. Publish the config with php artisan vendor:publish and pick the feeds entry from the list instead of guessing the tag name.
  • Upgrading from 1.x? Read the upgrade guide first — it shipped in this release specifically for this (#301, simplified in #307). The README was also rewritten to be clearer about the Laravel commands (#304), so the artisan surface is now documented rather than inferred. Run php artisan list | grep -i feed to confirm the names on your version.
  • Read the docs site: https://feeds.dragon-code.pro. Four pages carry most of the weight — api/config-attributes (what every config key does, now explicitly documented in #303), feed-targets (which targets ship in the box), receipt-target-feeds (a worked example end to end), and the 1.x → 2.x upgrade guide.
  • Then read the source. vendor/dragon-code/laravel-feeds/src is small. With 36 stars and 0 dependents there is no blog-post corpus and no Stack Overflow trail. The code and the docs site are the whole reference. Budget an hour.
  • First use case: one product feed for one marketplace. Point the config at your Product model, map the required fields, generate into storage/app/feeds/products.xml, validate the file against the marketplace's own checker, then put it on a schedule. Do not start with five targets — start with one you can validate by hand.

Implementation Patterns

  • Treat each feed as a config entry, not as code. One target, one file, one schedule. Per-locale and per-currency feeds are separate entries; do not try to branch inside a single feed.
  • Use the new per-feed converter attributes (#288) for exactly this. Converter settings no longer have to be global, so two marketplace feeds in the same install can format values differently without duplicating a generator. Keep those overrides in the feed's config entry next to the field mapping, so a reviewer sees both in one place.
  • Use the new per-item date format attribute (#286) instead of a custom formatter when a target wants a non-default date shape. This is the common case — dates are the first thing a marketplace rejects — and it used to force a custom formatter for a one-line change.
  • Feed generation belongs in a queued job, not in a controller. Wrap it, log the row count and the output size, and let the scheduler dispatch it. A 200k-row catalog will not finish inside a request.
  • Write to a temp path, then rename. feeds/products.xml.tmp → feeds/products.xml. Consumers poll these URLs; a half-written file served once can get the feed rejected or, worse, silently imported with missing rows.
$tmp = storage_path('app/feeds/products.xml.tmp');
$final = storage_path('app/feeds/products.xml');

$this->feed->generate($tmp);        // verify the real API surface in the source
rename($tmp, $final);               // atomic on the same filesystem
  • Iterate with the query builder or chunkById, never get(). The package exists because catalogs are large; loading the collection first defeats the point and will OOM on a real dataset.
  • Eager-load only what the feed fields need. with(['brand', 'category', 'images']) per chunk. Missing relations are fine, missing relation queries per row are not.
  • If you publish split feeds, note that 2.0 fixed the quadratic ownership lookups (#314) and now caps export batches at split capacity (#313). Re-run your split benchmark on upgrade — batch sizes may shift, and a config that relied on the old permissive behaviour can now silently truncate at the cap. Assert total exported rows against the source count in a test.
  • Prefer generating from slugs where the package now derives them from titles (#287) — it gives you stable, human-readable feed identifiers. But see the title change below before you assume the slugs are the same ones you had last week.
  • Keep a mapping layer between your model and the feed fields. When the marketplace changes a required field, you want to edit a mapper, not the feed class and not the config.
  • Serve the finished file through a route with cache headers, or push it to the marketplace over SFTP. Serving it from your app is simpler and easier to debug — do that until the marketplace forces otherwise.
  • Test it. Build three fixture products covering the awkward cases (missing price, empty category, special characters in the title), generate the feed in a test, assert the XML parses and assert two or three specific nodes. After the 2.0 upgrade, add a snapshot of the generated file to the test so the title/slug change shows up as a reviewable diff rather than a support ticket.

Gotchas and Tips

  • 2.0 is a major bump with a hard platform requirement: PHP 8.4, Laravel 13, Pest 5 (#297). Pin ^1.0 if you cannot move all three at once. Pest 5 is a test-suite change, not just a runtime one — your own tests around the generator may need updating too.
  • The "Feed" suffix was removed from feed titles (#293), and feeds can now be generated from title-derived slugs (#287). Those two land together: change the title, change the slug, change the URL. Anything that hardcoded the old feed name — a route, a sitemap entry, a URL already registered with the marketplace — needs checking before you deploy. Grep for the literal string.
  • Per-feed converter attributes and per-item dates add another configuration layer, so read api/config-attributes before setting anything: know whether a value is global, per-feed, or per-item, and which one wins. Guessing here produces a feed that is structurally valid and semantically wrong.
  • 2.0 contains real performance work (#313, #314, #315, #316 — per-row diagnostic path resolution, quadratic split lookups, repeated date resolution). Re-benchmark rather than trusting your old timings, and re-check memory ceilings. The --timeout and --memory you set to survive 1.x may now be far too generous — or, if the old numbers were the reason you chunked conservatively, verify chunking still behaves.
  • Memory is the failure mode, not correctness. First symptom of trouble is a timeout or an OOM in the queue worker, not a broken feed. Set --timeout and --memory on the worker deliberately.
  • XML escaping is where feeds die. Ampersands, quotes, emoji in product titles, and control characters all break parsers. Strip control chars before writing; escape everything else. Run the output through xmllint --noout in CI or in the job itself before publishing.
  • Marketplace rejection reasons are rarely in your app's logs. Log the row count, the file size, and a hash of the file. When support asks "which version did you send", you will have an answer.
  • Config caching: php artisan config:cache freezes env values. Anything per-environment (base URL, output disk) must come from env() in config/feeds.php, never from a runtime call inside the config array. This matters more now that converter and date settings can be nested per feed.
  • Localization, currency, and date format. A feed built with the wrong locale, currency code, or date shape passes every structural check and still gets rejected or, worse, imported at the wrong price or the wrong day. Assert all three in a test.
  • Extension points are the reason to pick this over hand-rolled XML. Custom targets, custom field formatters, and overridable templates are the usual seams — check config/feeds.php and the driver directory before writing a generator from scratch. If the built-in target is 90% right, extend it; do not fork the package.
  • Resource publications are now taggable (#306). If you filter, list, or route publications by tag, this is new surface to design against rather than something to retrofit later.
  • Supply chain: 36 stars, 0 dependents, one maintainer. Pin the version in composer.json, keep a test that runs the generator, and accept that an upstream break is yours to patch. The MIT license and small surface make that cheap; a large abstract dependency would not.
  • The release timeline metadata has been unreliable in the past (a listed last-release date in the future, [unverified]). Confirm the actual 2.0.0 publication and its composer.json constraints on Packagist directly before you plan the upgrade around it.
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core