descom/descommarket-feeds
descom/descommarket-feeds is a Laravel package for generating and managing Descom Market product feeds. It offers configurable feed generation, straightforward integration, and a convenient way to keep your product catalog synchronized with market feed requirements. Simplifies feed setup in Laravel...
Start by installing the package and publishing its config, since almost everything in a feed package is driven by configuration rather than by writing feed XML by hand:
composer require descom/descommarket-feeds
php artisan vendor:publish --tag=descommarket-feeds-config
Then read, in this order:
php artisan feed:generate {name}. That command name is your fastest path to a first successful run.Your first real use case should be the smallest possible end-to-end loop: point one feed at a single Eloquent model (e.g. Product), map three or four fields (id, title, price), generate it, and open the output file. Do not start by mapping every attribute — get one feed rendering, confirm the file lands on the right disk and is publicly reachable, then expand the mapping.
If the README is thin (likely, given the package's age and adoption), treat the source as the documentation. Grep for config( and class ... extends to find the extension points before writing any custom code.
Config-driven feed definitions. The intended pattern is to declare each marketplace feed in config and let the package handle serialization and delivery. Keep these definitions in config/descommarket-feeds.php (or split into per-channel files and merge), and keep the mapping logic declarative — field name to model attribute or closure.
Scheduled regeneration. Feeds are stale the moment a price or stock level changes. The standard workflow is to schedule the generation command and let it rebuild on a cadence appropriate to the marketplace:
// routes/console.php or Kernel::schedule()
$schedule->command('feed:generate google')->hourly()->withoutOverlapping();
$schedule->command('feed:generate facebook')->dailyAt('03:00');
Use withoutOverlapping() — feed generation on a real catalog routinely outlives the interval.
Model-level mapping via accessors or a dedicated presenter. Rather than stuffing feed formatting into config closures, expose feed-ready values on the model (or a small DTO/presenter) and reference those. This keeps currency formatting, image URL resolution, and availability logic testable outside the feed pipeline.
Multi-channel with a shared product source. One query/scope feeds many channels; only the attribute mapping differs. Define a single "feedable products" scope (published, in stock, has image) and reuse it across every channel config so you never ship a channel that includes drafts.
Storage and delivery. Publish to the public disk and let the marketplace pull the URL, or write to a private disk and push via SFTP/API if the package supports a destination driver. Prefer the pull model where possible — no credentials to rotate.
Invalidation hooks. Wire model events (saved, deleted on Product) to mark a feed dirty, and have the scheduled command regenerate only dirty feeds. This is the difference between a feed that runs every hour regardless and one that runs only when something changed.
Testing. Assert on the generated artifact, not on internal calls: generate a feed with a handful of factory products, then parse the XML/CSV and assert on rows and required attributes. Snapshot the output so mapping regressions surface as diffs.
composer.json (exact or ~) so a patch release does not silently change your output schema.gtin, a price without currency, a relative image URL, or a shipping block absent for a required country will get the whole feed rejected — often with an error that does not name the offending row. Validate locally against the marketplace's spec before uploading.http://localhost or a signed/expiring URL baked in. Resolve image URLs through Storage::disk(...)->url() or a configured CDN base, never asset() in a queued context.& in product titles and on invalid UTF-8 from supplier imports. If the package's serializer does not escape for you, sanitize at the mapping layer.config('app.currency'). Each channel config should carry its own currency and locale, and prices should be formatted from integers/minor units rather than floats.illuminate/* constraints in composer.json. If it targets an older major, expect to fork or shim the service provider.php artisan schedule:list), and check whether the package swallows exceptions during row mapping — silent per-row failures are common and produce a valid-looking feed with missing entries.How can I help you explore Laravel packages today?