liberusoftware/import-export-livewire
Import and export data in Laravel apps without leaving the page. Livewire-powered components handle file uploads, column mapping, row validation, and exports, making CSV/Excel workflows simple to add to admin panels and dashboards.
1. Confirm you actually need this package. liberusoftware/import-export-livewire is a presentation adapter — it wraps the underlying import/export domain module in Livewire components. It is not a standalone CSV/Excel library. Check that the base module (typically liberusoftware/import-export or the equivalent Liberu module) is installed alongside it, otherwise the components will resolve actions that don't exist.
2. Install and let module discovery run.
composer require liberusoftware/import-export-livewire
php artisan module:list # confirm the module registered
php artisan vendor:publish --tag=import-export-livewire-config
php artisan migrate # if the module ships import/export job or log tables
Liberu modules are conventionally nwidart/laravel-modules packages, so if the components don't appear, check modules_statuses.json and that the module's service provider is not disabled.
3. Read the source in this order (the repo has no meaningful docs, 0 stars, and an ambiguous license — you will be reading code, not tutorials):
composer.json → namespace, PSR-4 root, required Liberu packagessrc/Providers/*.php → what gets registered: Livewire components, routes, config merge, view namespacesrc/Livewire/ (or src/Http/Livewire/) → the actual components and their public propertiesresources/views/livewire/ → the Blade surface and what events it emitsconfig/ → disk names, chunk sizes, allowed mime types4. First use case. The lowest-risk first integration is a read-only export button on an existing index page:
<livewire:import-export::export-button :model="App\Models\Customer::class" />
(or whatever the registered alias resolves to — verify with php artisan livewire:list / grep the provider's Livewire::component() calls). Prove the export path end-to-end before touching imports, because imports carry file-upload, validation, and partial-failure semantics that are much harder to debug cold.
Treat the component as a controller, not a service. The adapter's job is: collect a file or a filter set → hand it to a domain action/job → reflect progress or errors back into the Livewire state. Keep your business rules (column mapping, which fields are importable, tenancy scoping) in your own importer/exporter classes and inject or resolve them from the Livewire component. If you find yourself writing mapping logic inside a Blade view or a component property, you've put it in the wrong layer.
Embedding vs. extending. Two viable patterns:
:model, :disk, :columns). Fastest, but you're limited to the props the package exposes.mount() to inject authorization and default filters. Prefer this once you need per-tenant scoping, which the package almost certainly doesn't know about.Authorization is your responsibility. Wrap the component in a policy check in the Blade template:
@can('export', App\Models\Customer::class)
<livewire:import-export::export-button :model="App\Models\Customer::class" />
@endcan
Livewire components are addressable over the wire (/livewire/update), so a hidden button is not access control. Enforce it in mount() or authorize() inside the component as well.
Imports: assume the happy path is the exception. A robust integration pattern for this kind of adapter:
WithFileUploads, immediately storeAs() on a dedicated imports disk (not local).mimes:csv,xlsx.Progress and polling. Exports of any real size should be queued with a "download when ready" notification. If the package exposes a progress event or status property, drive it with wire:poll.5s; otherwise wrap the vendor component and poll your own import/export record. Beware wire:poll on a component that holds a temp upload — polling re-renders and can invalidate the temp file in older Livewire versions.
Pair it with the non-Livewire surface. The same domain actions should back an artisan command and an HTTP endpoint. Your test suite should exercise the command, not the Livewire component, for coverage of the actual import logic — Livewire tests are slow and the adapter is thin.
License is NOASSERTION. This is not "probably MIT." Before this touches a commercial codebase, get the actual license file from the repo and have it reviewed. A package with no clear license is a legal unknown, not a permissive one.
Zero stars, zero dependents, dated 2026-10-26. The metadata is anomalous (a release date in the future, no stars, no dependents). Treat it as pre-production: pin an exact version in composer.json, commit the lock file, and be prepared to vendor the source into your repo (repositories with a path type) so an upstream force-push can't break your build. Do not ^-range this.
It is an adapter — most "bugs" are missing base-module wiring. If a component 500s on Class not found, or the download never appears, the fault is almost always in the underlying import/export service, a queue worker that isn't running, or a missing storage link. Check php artisan queue:work is consuming the right queue before you read a single line of the component.
Temp file lifecycle bites. Livewire's WithFileUploads puts files in livewire-tmp and cleans them up on a timer. If your import dispatches a job that reads the file later, you must store() it to a permanent disk synchronously — otherwise the job runs after the reaper has deleted it, and you get an intermittent "file not found" that only appears on slow queues. Same trap for the "download export" link: generate it on a persistent disk, not a temp one.
Disk configuration is the #1 silent failure. storage/app/private vs public, and Storage::disk() defaults differing between local in dev and S3 in prod, will make an export work locally and 404 in production. Explicitly set the disk in config and add a smoke test that hits the download URL.
Memory and timeouts on import. maatwebsite/excel-style imports blow up on memory_limit around the 10k-row mark if you use ->get() instead of ->queue()/->chunk(). And PHP-FPM's max_execution_time won't save you if the parsing is synchronous — another reason to force the queued path even for "small" files.
Extension point to look for first. Config keys for disk, chunk_size, allowed_extensions, and the component namespace. If the package lets you swap the importer/exporter class via config or a container binding, that is your cheapest customization route — take it before subclassing.
Test in isolation. Write one Feature test that mounts the component as an authorized user and asserts the queued job was dispatched (Queue::fake()), and one unit test per importer class. That gives you upgrade safety for a package with no community to catch regressions.
How can I help you explore Laravel packages today?