laravel-enso/data-import
Laravel Enso Data Import provides structured Excel and CSV imports for Laravel apps, with configurable templates, validation, queued processing, and reusable workflows that integrate with Enso's UI and permissions.
This is not a standalone import package — it is a module in the Laravel Enso ecosystem and assumes laravel-enso/enso (core, menus, permissions, Vue UI) is already installed. Confirm your Enso/Laravel version first; the 2019 release targets the Laravel 5.8–6.x era.
Minimal steps:
composer require laravel-enso/data-importphp artisan enso:install or the package's publish/migrate steps) to publish migrations, config, and frontend assets.php artisan migrate to create the imports table(s).config/imports.php (or config/enso/imports.php) — file disk, size limits, chunk defaults.Import model and its statuses — this is your progress/audit record.Importable contract or base class) — this is the extension point you implement per entity.First use case: import a simple flat entity (e.g. companies or products). Create one importer class that declares the sheet(s), header/start row, chunk size, per-row validation rules, and a save/process method. Upload a small XLSX through the Enso UI, watch the Import record change status, then inspect stored row errors. Once that works end-to-end, generalize into templates for repeatable imports.
One importer class per entity. Keep the class thin: sheet definition, start row, chunk size, validation rules, and a persistence callback. Put domain logic (matching, normalization, upserts) in a service the importer calls. This keeps importers reusable across UI uploads and artisan commands.
Template-driven mapping. The package's templating is its main differentiator: define expected columns/headers once, then validate uploaded files against the template (missing columns, wrong sheet name, unexpected headers) before touching the database. Treat the template as a contract and version it when columns change, otherwise old files silently import wrong data.
Two-pass validation. Run a validation-only pass (or per-row Validator::make) that records failures with row numbers, then only commit if the operator accepts the error report. For large files, validate per chunk and persist row errors to a companion table rather than aborting the whole import on row 4,000.
Chunked processing with queues. Read with Spout in chunks (chunkSize ~500–1000), dispatch a job per chunk or per import, and update the Import status/progress counters. Never load the whole sheet into memory, and never do one save() per row in a tight loop — collect rows and use insertOrIgnore/upsert in batches.
Idempotent upserts. For re-imports, key on a natural/business key (SKU, email, external ID) rather than auto-increment IDs, and use upsert. Decide explicitly whether blank cells mean "skip" or "null out the column" — encode that in the importer, not in ad-hoc controllers.
Transaction boundaries. Wrap each chunk in a transaction, not the whole file. Record chunk completion so a failed job can resume rather than duplicate rows. Keep an errors payload on the import record for the UI.
Integration hooks. Use model events or the package's import lifecycle events (started/finished/failed) to trigger cache clears, search reindexing, or notifications. If the package doesn't emit what you need, wrap the service call in your own job that does.
Testing. Keep small fixture XLSX files in tests/Fixtures, fake the storage disk, and assert both the import status and the resulting DB state. Test the header-mismatch and invalid-row paths, not just the happy path.
box/spout, which is unmaintained and replaced by openspout. On PHP 8.1+ you will likely hit deprecations or hard failures. Fork the package or budget a migration to openspout (or Laravel Excel) before committing to it.config.platform or use --ignore-platform-reqs only as a stopgap, and verify every Enso dependency version together.maatwebsite/excel is usually the better trade.startRow. Assert the convention with a deliberately broken fixture before trusting error messages in production.array_filter($row) and guard against all-null rows before validation, or you'll generate noise errors.--timeout, --memory, and retry_after adjusted; otherwise workers are killed mid-chunk and you get partial data. Prefer many small chunk jobs over one long job.How can I help you explore Laravel packages today?