NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Imports for Laravel

Templates and error reports

Every importer has a ready-to-fill template, as an XLSX workbook or a CSV file, with headers in the requested locale:

use RoundlyConsulting\Imports\Enums\TemplateFormat;
use RoundlyConsulting\Imports\Facades\Imports;

return Imports::template('assets', TemplateFormat::Xlsx, locale: 'sk')->download();
Imports::importer('assets')->template(TemplateFormat::Csv)->store('s3', 'templates/assets.csv');
$path = Imports::template('people')->toTemporaryFile();       // you own (and delete) the file
  • Columns are the importer’s fields in order, minus excludeFromTemplate(). Headers are labels in the requested locale (fallback: the app fallback locale, then the field name); required fields end with “ *”.
  • An example row (templates.example_row, on by default): each field’s example() or a sample for its type.
  • CSV: UTF-8 with a BOM (templates.csv_bom), the delimiter per locale (templates.csv_delimiter: comma, Slovak semicolon), plus a hint row (templates.hint_row.csv): required or optional, allowed values, a date example, Yes/No, the reference columns.
  • XLSX: a bold, frozen header; column widths; text columns formatted @ so leading zeros survive, dates yyyy-mm-dd, decimals 0.00…; dropdowns (templates.data_validation) for choice and yes/no columns — inline when the list fits 255 characters, else a hidden Lists sheet and a defined name; an input message per column (label and hint). No hint row by default (templates.hint_row.xlsx).
  • An unchanged example row or a hint row left in an uploaded template is recognised and skipped (counted as templateRows), in any shipped locale — but only in the first two non-blank data rows, where a template puts them. A real row further down whose values equal the examples imports normally.

The Template object

$template = Imports::template('assets');

$template->format;                    // TemplateFormat
$template->filename;                  // assets.xlsx — the label as a slug in the template's locale
$template->download('assets-template.xlsx');   // StreamedResponse
$template->store('s3', 'templates/assets.xlsx');
$template->toTemporaryFile();
$template->contents();

download() sends an attachment with an ASCII-safe filename and a UTF-8 filename*, plus X-Content-Type-Options: nosniff, and removes the temp file after sending. The temp file is also removed when the object is destroyed — except one you took with toTemporaryFile(), which you own.

From the command line

php artisan imports:template assets --format=csv --locale=sk --output=assets.csv

Error reports

return $session->errorReport(TemplateFormat::Xlsx)->download();   // assets-errors.xlsx
$session->errorReport(TemplateFormat::Csv, 'sk');                    // the report's own labels in Slovak

The report holds the original header row plus an Errors column, with only the failing rows — invalid at preview, failed at commit — as uploaded, ready to fix and re-upload. It is named after the upload (assets-errors.xlsx), defaults to XLSX and asks authorize(View). The locale argument renders the report’s own labels (the Errors column, the sheet name, unnamed columns) in that language; the messages stay in the session’s locale and the uploaded headers stay as uploaded. A file batch’s report has two columns, File and Errors, one row per refused file.

Formula injection

Every CSV the package writes — templates and error reports, which echo values other people uploaded — prefixes ' to a cell starting with = + - @, a tab or a CR; a plain number (-5, 1,25) is left alone. Reading a CSV strips that ' again. XLSX output is safe by construction: inline strings, never formulas.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.