Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Import Export Laravel Package

liberusoftware/import-export

A Laravel package for importing and exporting data with configurable sources, formats, and field mappings. Define import/export workflows, handle validation and transformations, and move data between files and your application cleanly.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm the package is real for your setup before you build on it. With zero stars and zero dependents, treat this as an internal-grade module: read the source in vendor/liberusoftware/import-export first, and pin an exact version in composer.json rather than a caret constraint.

composer require liberusoftware/import-export --with-all-dependencies
"liberusoftware/import-export": "1.x.y"

2. Publish and read the config before touching anything else. Liberu modules conventionally ship a service provider plus publishable config and migrations. Look for:

php artisan vendor:publish --provider="Liberu\ImportExport\ImportExportServiceProvider"

Then inspect config/import-export.php for the pieces named in the description: queue connection/name, storage disk for uploads and error reports, chunk size, retention window, and the authorization gate names. If the provider auto-registers in your Liberu application, you may only need config/import-export.php. Run migrations only if the package persists run state.

php artisan migrate
php artisan route:list | grep -i import

3. Find the two contracts that matter. Everything in this package orbits two abstractions:

  • a schema/definition class that declares the columns, types, and validation rules for an import or export;
  • a mapping layer that translates external headers to those schema fields.

Grep for Schema, Definition, Mapping, Import, Export in the vendor directory and copy the package's own test fixtures as your template — those are the only guaranteed-correct usage examples in a package this young.

4. First use case: a dry-run CSV import of one small model.

// Illustrative — verify class names against the source.
$run = Import::make(ContactsImportSchema::class)
    ->file($request->file('csv'))
    ->mapping(['Email Address' => 'email', 'Full Name' => 'name'])
    ->dryRun()
    ->dispatch();

return redirect()->route('imports.show', $run);

A dry run is the right first call because it exercises schema parsing, mapping, and validation without writing rows — so a failure tells you the definition is wrong, not your data.

Implementation Patterns

Dry run → review → commit is the intended lifecycle. Do not offer users a one-click "import" button. The pattern that pays off:

  1. Upload → dry run → store the run record.
  2. Show the user a summary: N valid, M invalid, sample errors.
  3. User confirms → dispatch the real run against the same stored file and mapping.

This means your upload persistence must outlive the request. Store the file on a disk, keep the path on the run record, and never re-upload between dry run and commit.

Mapping should be a first-class, user-visible step. Header-based auto-mapping is convenient but wrong often enough that you need an override UI. Keep the mapping array in your own table (or the run's payload) so re-runs and retries are reproducible:

$mapping = $schema->guessMapping($csvHeaders); // then let the user correct it

Store the resolved mapping alongside the run; a retry that re-guesses can silently change semantics.

Queue the execution — always. Even a 200-row CSV should go through the queue, because the package's progress and error-report features assume an async run. Configure a dedicated queue so a large import can't starve your web jobs:

// config/import-export.php
'queue' => ['connection' => 'redis', 'queue' => 'imports'],
php artisan queue:work redis --queue=imports,default

Progress: poll, don't push. Poll a lightweight status endpoint from your UI on a 2–5s interval. Return only counters (processed, total, failed, status) — not the error list — so the endpoint stays cheap under polling. Use wire:poll or a small setInterval fetch, and stop polling on terminal states.

Error reports are the deliverable, not a debug artifact. Wire the package's error report export straight into your UI as a downloadable CSV keyed to the same headers the user uploaded. That lets them fix their file in Excel and re-import with zero translation. Preserve the original row number in the report.

Authorization belongs at the boundary, in your app. Whatever gate/policy hooks the package exposes, wrap your own routes with your own policy as well:

Route::middleware(['auth', 'can:import,App\Models\Contact'])->group(function () {
    // upload, dry run, confirm, download report
});

Never rely on a package default for tenant isolation — enforce team_id/tenant_id scope in your schema's base query.

Chunked, resumable writes. For anything over a few thousand rows, ensure the schema performs upserts inside chunks and that failures are recorded per-row rather than aborting the run. Prefer upsert on a natural key so a partial run can simply be re-dispatched.

Retention is a scheduled concern. The package will prune old runs and reports; register the schedule and make sure your own storage disk cleanup matches it, or you'll leak uploaded CSVs forever.

$schedule->command('import-export:prune')->daily();

Gotchas and Tips

Zero stars and zero dependents means you are the QA team. There is no Stack Overflow corpus for this package. Budget a half-day reading the source and its tests before committing to it in a production path, and check the release history for churn — the recent release date with no adoption is a signal to pin hard and read changelogs.

Assume the docs are thin. The description reads like a feature list, not a manual. Every API call in this assessment should be verified against vendor/ before you write it into a controller.

CSV encoding will bite you first. Watch for UTF-8 BOMs breaking the first header match, CRLF line endings, semicolon delimiters from European Excel, and leading =/+/- in cells (CSV injection — sanitize on export). Strip the BOM explicitly and let users pick a delimiter if the schema allows it.

Dry run still parses the whole file. "Dry" means "no writes," not "cheap." Large files will still churn CPU and memory — keep the dry run queued too, and cap upload size at the request-validation layer.

Validation parity is the classic bug. App-level rules and DB constraints disagree: string max lengths, nullable vs. empty-string, case-insensitive uniqueness, foreign keys. Import fails at the database after passing validation and the error report blames the wrong row. Test with a deliberately messy fixture (duplicates, empties, 300-char strings, unknown FK ids).

Date and number coercion. Spreadsheet exports mangle dates into serial numbers and strip leading zeros from phone numbers and postcodes. Force these fields to strings in your schema definition and coerce explicitly, rather than trusting the package's type inference.

Transaction boundaries. If each chunk is its own transaction, a mid-run failure leaves you half-imported — acceptable only if the operation is idempotent (upsert on natural key). If it isn't, add a run-level marker and make partial state visible to the user instead of pretending it's all-or-nothing.

Retries must be idempotent. Queued jobs retry. A retried import that inserts instead of upserts produces duplicates that look like a mapping bug. Set tries, backoff, and timeout deliberately, and consider ShouldBeUnique on the run to prevent double dispatch from an impatient double-click.

Progress lies at the edges. Counter updates may lag by a chunk, and total is often unknown until the file is fully scanned. Display "processed X" rather than a fake percentage, and make the terminal state authoritative.

Test with Queue::fake() for the dispatch contract and Bus::fake() sparingly. Assert that the job carries the run id and disk path, then test the job itself directly with a real (small) file — that's where the mapping and validation logic actually lives.

Extension points to look for, in priority order: custom field validators/mappers, events fired per row or per run (hook notifications and audit logs there rather than editing vendor code), and a swappable error-report formatter. If none exist, subclass the schema rather than forking — and note that for a package this unproven, a fork may be the honest long-term answer.

Decide the fallback now. For a critical import path, weigh a hand-rolled chunked importer against this dependency. This package's value is the dry-run/progress/error-report surface — if you can't get that working against real files in an afternoon, the dependency is costing more than it saves.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment