The Imports facade
Everything goes through one facade, RoundlyConsulting\Imports\Facades\Imports, sugar over the ImportsManager singleton. It is also registered as the global alias Imports:
use RoundlyConsulting\Imports\Enums\{SessionStatus, TemplateFormat};
use RoundlyConsulting\Imports\Facades\Imports;
// Importers and templates
Imports::importers()->available($user, $team);
Imports::register(AssetsImporter::class);
Imports::importer('assets')->descriptor('sk');
Imports::template('assets', TemplateFormat::Xlsx, locale: 'sk')->download();
// Everything for one owner — the entry point HTTP code uses
$imports = Imports::for($team)->by($user);
$session = $imports->upload('assets', $request->file('file'));
$files = $imports->uploadFiles('documents', $request->file('files'));
$imports->sessions('assets', SessionStatus::Previewed)->paginate();
$imports->session($id)->counts();
$imports->batch($id)->summary();
$imports->mappings('assets')->all();
$imports->running('assets');
// Trusted paths, the reader and housekeeping
Imports::session($model); Imports::batch($id);
Imports::read($request->file('file'));
Imports::sweep(); Imports::prune();The whole flow, start to finish:
$session = Imports::for($team)->by($user)->upload('assets', $request->file('file')); // checked + stored
$session->suggestMapping(); // MappingSuggestion (applied already when complete)
$session->map(['Inventory no' => 'asset_tag', 'Name' => 'name']) // optional: by header text or column number
->saveMapping('ERP export'); // optional: reused for identical headers
$session->mode(DuplicateMode::Update)->preview(); // ≤ 500 rows: now; more: queued (poll isPreviewed())
$session->counts(); // ImportCounts
$session->rows(RowFilter::invalid())->paginate(50);
$batch = $session->commit(); // a Laravel job batch
$batch->progress();
$batch->summary();
$batch->rollback(); // within imports.undo.windowManager methods
| Method | Returns | Does |
|---|---|---|
for(Model $owner) | OwnerImports | The owner-scoped entry point — uploads, sessions, batches, saved mappings. HTTP code uses only this. |
importers() | Accessors\Importers | all(), find(), has(), describe(), available() — discovery for a UI. |
register(string ...$classes) | void | Runtime registration beside imports.importers. |
importer(string $key) | ImporterHandle | descriptor(), template(), modes() — UnknownImporterException for an unknown key. |
template(string $importer, ?TemplateFormat $format = null, ?string $locale = null) | Template | A CSV or XLSX template; the format defaults to imports.templates.default_format. |
session(ImportSession|int|string $session) | SessionHandle | Trusted path, no owner check — ImportNotFoundException when missing. |
batch(ImportBatch|int|string $batch) | BatchHandle | The same for a batch. |
read(ImportSource|UploadedFile|string $file, string|int|null $sheet = null, ?string $delimiter = null, int $headerRow = 1) | SpreadsheetFile | The standalone reader — no session, nothing stored. |
prune() · sweep() | PruneReport · SweepReport | What imports:prune and imports:sweep run. |
Imports::fake() | ImportsFake | Facade only — the recording fake (see Testing). |
container() and perform() are public on the manager but internal — perform() is the funnel every handle runs its action through, the hook the fake records with. Don’t call them from app code.
Imports::for($owner)
| Method | Returns | Does |
|---|---|---|
by(Authenticatable|Model|null $actor) | OwnerImports | A copy acting as $actor — LogicException when it is not an Eloquent model. |
upload(string $importer, ImportSource|UploadedFile|string $file, string|int|null $sheet = null, ?string $delimiter = null, int $headerRow = 1, ?string $locale = null) | SessionHandle | Check, store and open a session. authorize(Upload) runs before the file is read. |
uploadFiles(string $importer, iterable<UploadedFile>|UploadedFile $files, ?string $locale = null) | SessionHandle | A file batch: many files or ZIP archives. |
sessions(?string $importer = null, SessionStatus ...$status) | Builder<ImportSession> | Newest first — one importer (refused unless the actor may view it) or every importer the actor may view. |
session(int|string $id) · batch(int|string $id) | SessionHandle · BatchHandle | Another owner’s id is ImportNotFoundException (404). |
mappings(string $importer) | SavedMappingsHandle | all(), find(), save(), delete(). |
running(string $importer) | ?SessionHandle | The session currently committing or rolling back. |
$sheet is a name (exact, then case-insensitive) or a 1-based position among visible sheets; $headerRow is 1-based; $locale is the session locale — labels, messages and the decimal separator.
The session handle
Mutators return the handle, so a flow chains. Reads ask authorize(View) once per handle; writes ask their own operation. Source, mapping, mode, preview and discard are refused with ImportStateException once a commit holds the session:
| Method | Returns | Does |
|---|---|---|
by($actor) · model() · id() | SessionHandle · ImportSession · int|string | A copy acting as $actor; plain accessors. |
status() | SessionStatus | Re-read from the database — View. |
isValidating() · isPreviewed() · isCommitted() | bool | Committed = committing or any later status — View. |
sheets() · headers() | list<SheetInfo> · list<string> | A blank header reads Column C — View. |
useSheet($sheet) · useDelimiter($delimiter) · useHeaderRow($row) | self | Change how the stored file is read; the preview is dropped — Upload. |
suggestMapping() | MappingSuggestion | View. |
map(array|ColumnMapping $mapping) · saveMapping(string $name) | self | Upload. |
mode(DuplicateMode $mode) | self | Upload. |
preview(?bool $queue = null) | self | null: inline up to preview.sync_threshold, else queued; true / false forces it — Upload. |
counts() · previewData() · progress() | ImportCounts · ImportPreview · Progress | progress() has phase preview, or the batch’s while committing — View. |
rows(?RowFilter $filter = null) | RowQuery | paginate(), cursor(), count() — View. |
errorReport(TemplateFormat $format = TemplateFormat::Xlsx, ?string $locale = null) | Template | Failing rows plus an Errors column — View. |
commit() | BatchHandle | Commit. |
cancel() | self | Cancels the running batch, if any — Commit. |
discard() | self | Deletes the file and row results — Upload. |
batch() | ?BatchHandle | View. |
The batch handle
| Method | Returns | Does |
|---|---|---|
by($actor) · model() · id() | BatchHandle · ImportBatch · int|string | A copy acting as $actor; plain accessors. |
session() | SessionHandle | View. |
status() | BatchStatus | Re-read — View. |
isRunning() · isFinished() · isRolledBack() | bool | pending/running · completed/failed/cancelled · undone — View. |
progress() | Progress | phase commit (chunks) or rollback (created records) — View. |
summary() | ImportSummary | View. |
records(?RecordAction $action = null) | Builder<ImportedRecord> | Ledger rows ordered by row number — View. |
cancel() · resume() | self | Commit. |
rollback() | self | Rollback. |
canRollback() | bool | Completed/failed/cancelled, no rollback yet or a failed one, before undo_until — View. |
rollbackReport() | ?RollbackReport | Once a rollback finished or failed — View. |
Importers, templates and saved mappings
- Imports::importers() — all() (every ImportDefinition), find($key), has($key), describe($key, ?$locale), available(?$user, $owner, ?$locale).
- Imports::importer($key) — descriptor(?$locale), template(?$format, ?$locale), modes() (empty for a file importer).
- Template — format and filename properties; download(?$filename), store($disk, $path), toTemporaryFile(?$target), contents().
- Imports::for($owner)->mappings($importer) — all(), find($name), save($name, $columns), delete($name).
- RowQuery ($session->rows($filter)) — paginate($perPage = 50, ?$page), cursor(), count().
Value objects, DTOs and enums
- Definitions (Definition\): Field, NaturalKey, Ownership, ChangeDetection, FileRules, FileDuplicates, Limits, FieldChange. Callback arguments (Rows\): ImportRow, ImportContext, ImportFile. Reading (Reading\): SpreadsheetFile, Cell, ReadOptions.
- DTOs (final readonly): ImportSource, UploadData, UploadFilesData, SaveMappingData, ColumnMapping, MappedColumn, MappingSuggestion, SuggestedColumn, SavedMapping, SheetInfo, ImportCounts, ImportPreview, RowFilter, RowResult, CellError, RecordReference, Progress, ImportSummary, RollbackReport, ImportedRecordView, ImportAudit, FileReference, ImporterDescriptor, FieldDescriptor, OptionDescriptor, PruneReport, SweepReport, DoctorFinding.
- Models (swappable via imports.models.*): ImportSession, ImportBatch, ImportRowResult, ImportedRecord. ImportSession and ImportBatch have handle() and countOf(string $key) — one stored count (valid, creates, created, …), 0 when absent; the static ImportSession::count() is Eloquent’s row count.
- Enums are string-backed, use enums-for-laravel’s helpers (label(), labels(), options(), values(), fromLabel(), is(), …) and translate their labels in English and Slovak:
| Enum | Cases |
|---|---|
SessionStatus | uploaded, needs_mapping, mapped, validating, previewed, preview_failed, committing, completed, failed, cancelled, rolling_back, rolled_back, rollback_failed, discarded, expired — plus ::beforeCommit(), ::undoable(), isBeforeCommit() |
BatchStatus | pending, running, completed, failed, cancelled |
RollbackStatus | rolling_back, rolled_back, rollback_failed |
RowStatus · RowOutcome | valid, invalid, duplicate_in_file, matched, failed · create, update, skip |
RecordAction | created, linked, updated |
RollbackOutcome | deleted, handled, kept, kept_changed, missing, failed |
DuplicateMode | skip, update, create_new |
ImportOperation | view, upload, commit, rollback |
ImportKind | rows, files |
FieldType | text, integer, decimal, boolean, date, datetime, email, choice, reference |
SourceFormat · TemplateFormat | csv, xlsx |
CellType | text, number, boolean, date, error |
MappingSource | saved, name, label, alias, fuzzy, manual, suggested |
DelimiterSource | sniffed, hint (sep=), override |
RejectionReason | 27 cases — see Reading files |
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 cryptoBy 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.