doefom/statamic-export
A Statamic addon for exporting entries and other content to CSV, JSON, and Excel files, with flexible field selection and filtering. Useful for backups, migrations, and passing data to spreadsheets or external tools.
composer require doefom/statamic-export and let Statamic's addon auto-discovery register the service provider; run php artisan vendor:publish --tag=statamic-export-config (or check the README for the exact tag) to get config/statamic-export.php into your app, then php artisan config:clear.storage/app/.... Once that round-trip works, move the same export into an Artisan command so it can be scheduled.Ad-hoc exports for editors. Use the CP bulk action when the request is "can I get this list in Excel?" — no deploy needed. Scope it by selecting a subset of entries, and keep column selection in the config so non-developers get a consistent shape.
Programmatic exports. Wrap the package's export class in an Artisan command or a controller endpoint and drive it from your own query/filter logic. This is the pattern for recurring deliverables (nightly stock list, monthly report) and for anything triggered by a webhook:
// Console command
public function handle()
{
Export::collection('orders')
->site('default')
->export(storage_path('exports/orders-' . now()->format('Y-m-d') . '.csv'));
}
Then $schedule->command('export:orders')->dailyAt('02:00') in routes/console.php / the scheduler.
Column mapping as configuration. Define the field handles you want exported once, in config or in a dedicated export class, rather than hand-rolling ->map() on every call site. Blueprint field handles change; keeping the mapping in one place means a single diff when a client renames a field.
Format and delivery. CSV for machine consumption and re-import; XLSX when the file goes to a human. Standardise filenames with a timestamp/version suffix so overwrites don't silently eat history, and push large files to S3 or a mail attachment rather than leaving them on local disk.
Big exports. Anything over a few thousand entries should be queued (ShouldQueue on your wrapper command or a job) and written to a temp path, then moved. Chunk your own query if you're pre-filtering, so the package isn't asked to hold the whole collection in memory.
Testing. Storage::fake('exports') plus an assertion on the generated file's contents is a cheap regression test. Assert on the header row and a couple of known cells; that's exactly where a normalisation change like the one in v0.8.1 will bite you.
1/true/null leaking into spreadsheets as mixed types), but it is observable: numbers, booleans and dates now arrive as text. Excel will treat "0123" as a string (good), but it also won't auto-sum a numeric column, and booleans may render as 1/0/"" rather than TRUE/FALSE. If a downstream importer or pivot table expects typed cells, cast explicitly on the consuming side — don't assume the file preserved types.; instead of , — otherwise the whole file lands in one column.storage/app/private vs storage/app/public trips people up), check php artisan config:clear after any config edit, then check storage/logs/laravel.log for the underlying exception — the CP action fails quietly-ish.How can I help you explore Laravel packages today?