PHPackages                             waad/filament-import-wizard - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. waad/filament-import-wizard

ActiveLibrary[Queues &amp; Workers](/categories/queues)

waad/filament-import-wizard
===========================

A powerful, queue-powered CSV and Excel import wizard for Filament with smart column mapping, relationship linking, and background processing for 100K+ rows.

v1.1.0(2mo ago)9711—2.2%1MITPHPPHP ^8.2

Since Apr 14Pushed 2mo agoCompare

[ Source](https://github.com/waadmawlood/filament-import-wizard)[ Packagist](https://packagist.org/packages/waad/filament-import-wizard)[ RSS](/packages/waad-filament-import-wizard/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (4)Dependencies (6)Versions (5)Used By (0)

Filament Import Wizard
======================

[](#filament-import-wizard)

A powerful, queue-powered CSV and Excel import wizard for Filament with smart column mapping, relationship linking, Spatie Translatable support, locale merge, dynamic schema validation, and background processing for 100K+ rows.

[![Dark Mode Support](https://camo.githubusercontent.com/663bb152287b0ad212d4c2f817605f8b93d84863e342de928e2bd84c309a48a2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4461726b2532304d6f64652d537570706f727465642d626c7565)](https://camo.githubusercontent.com/663bb152287b0ad212d4c2f817605f8b93d84863e342de928e2bd84c309a48a2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4461726b2532304d6f64652d537570706f727465642d626c7565)[![PHP 8.2+](https://camo.githubusercontent.com/2795c86d2dea6aba6285347c2adef64310db832ec1d2d634a32e3b51115a5c95/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d373737424234)](https://camo.githubusercontent.com/2795c86d2dea6aba6285347c2adef64310db832ec1d2d634a32e3b51115a5c95/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d373737424234)[![Laravel 10+](https://camo.githubusercontent.com/12e6a44c1a30425829945fa267b6a20e85c9f62642f4e7517f8467e20e72eee6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302532422d464632443230)](https://camo.githubusercontent.com/12e6a44c1a30425829945fa267b6a20e85c9f62642f4e7517f8467e20e72eee6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31302532422d464632443230)[![Filament 4.x/5.x](https://camo.githubusercontent.com/5c7be8fcacc6ebfbfe947fb3fb2073fdde039b90cd602b8d049ad35cf635742f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c616d656e742d342e78253246352e782d463539453042)](https://camo.githubusercontent.com/5c7be8fcacc6ebfbfe947fb3fb2073fdde039b90cd602b8d049ad35cf635742f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f46696c616d656e742d342e78253246352e782d463539453042)[![License: MIT](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)](https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e)

    2026-05-21.02.35.19.mp4    ✨ Features
----------

[](#-features)

- **4-Step Import Wizard** — Upload, map columns, review data, and import inside a Filament modal
- **Reverse Mapping UI** — Model fields shown first with CSV column dropdowns, not the other way around
- **Smart Auto-Mapping** — Automatically maps CSV headers to model fields using snake\_case matching (e.g., `Title` → `title`, `CategoryId` → `category_id`)
- **Relationship Linking** — Link or create related records (`BelongsTo`) with intelligent auto-increment ID handling
- **Spatie Translatable Support** — Detect `HasTranslations` traits and JSON columns; supports `whereJsonContains()` for cross-DB translated lookups
- **Locale Merge** — Combine multiple language columns (e.g., `title_en`, `title_ar`) into a single JSON translatable field with checkbox toggle
- **Locale-Aware Relation Lookup** — Find or create related models using translated column values
- **Upsert Support** — Update existing records instead of creating duplicates via configurable keys
- **Queue-Powered Processing** — Chunked batch execution with live progress tracking for large datasets
- **Eloquent Event Firing** — Inserts fire model `boot()`, observers, timestamps, and lifecycle hooks via individual `save()`
- **Dynamic Schema Validation** — Auto-generate validation rules from database column types (required, numeric, boolean, date, email, unique)
- **Error Review** — Inline validation and error download before import
- **Multi-Tenancy Ready** — Built-in team and tenant scoping across queue boundaries
- **Standalone Mode** — Use as a Livewire component outside Filament panels
- **Dark Mode** — Full dark theme support out of the box
- **Custom Queue Configuration** — Configurable queue connection and queue name per import
- **Excel Empty Column Trimming** — Automatically strips trailing empty Excel columns (no more 256-column UI)

📦 Installation
--------------

[](#-installation)

```
composer require waad/filament-import-wizard
```

### Publish Configuration &amp; Migrations

[](#publish-configuration--migrations)

```
# Publish config file (optional)
php artisan vendor:publish --tag="filament-import-wizard-config"

# Publish and run migrations
php artisan vendor:publish --tag="filament-import-wizard-migrations"
php artisan migrate
```

> ⚠️ If there are errors for CSS, try rebuilding Filament assets: `php artisan filament:assets`

🚀 Usage
-------

[](#-usage)

### Basic Usage in Filament Resource

[](#basic-usage-in-filament-resource)

Add the import action to your Filament resource's table. Example (`app/Filament/Resources/Posts/Pages/ListPosts.php`):

```
use Waad\FilamentImportWizard\Actions\ImportWizardAction;

protected function getHeaderActions(): array
{
    return [
        ImportWizardAction::make(),
    ];
}
```

### Advanced Configuration

[](#advanced-configuration)

```
ImportWizardAction::make()
    ->forModel(\App\Models\Product::class)
    ->chunkSize(500)               // Process 500 rows per job
    ->enableUpsert(true)           // Update existing records
    ->upsertKeys(['sku'])          // Match by SKU field
    ->queueConnection('redis')     // Custom queue connection
    ->queueName('imports');        // Custom queue name
```

### Standalone Usage

[](#standalone-usage)

Use the wizard outside of Filament panels via Livewire:

```
@livewire('filament-import-wizard', ['modelClass' => \App\Models\Product::class])
```

⚙️ Configuration
----------------

[](#️-configuration)

```
// config/filament-import-wizard.php

return [
    'modal_width' => Width::Full,        // Modal width (Filament Width enum)
    'chunk_size' => 1000,                // Rows per queue job
    'default_csv_delimiter' => ',',      // CSV delimiter (comma, semicolon, tab)
    'queue_connection' => null,          // Queue connection (null = default)
    'queue_name' => null,                // Queue name (null = default)
];
```

### Configuration Options

[](#configuration-options)

OptionDefaultDescription`modal_width``Width::Full`Width of the import wizard modal`chunk_size``1000`Number of rows processed per queue job`default_csv_delimiter``,`Default CSV delimiter for parsing`queue_connection``null`Queue connection to use (`null` = Laravel default)`queue_name``null`Specific queue name (`null` = default queue)📋 Import Steps
--------------

[](#-import-steps)

### Step 1: Upload

[](#step-1-upload)

Upload your CSV or Excel file. Supported formats:

- CSV (`.csv`) — with UTF-8 BOM auto-detection
- Excel (`.xlsx`, `.xls`) — trailing empty columns are automatically trimmed

### Step 2: Map Columns

[](#step-2-map-columns)

The mapping step presents **model fields first**, with a clean table-based layout:

- **Model Fields Section** — Each model field is displayed with its label, code name, and a dropdown to select which CSV column maps to it
- **Relations Section** — Each `BelongsTo` relation is shown with its FK/PK badges and a searchable field dropdown
- **Unmapped Columns Section** — CSV columns that are not mapped appear at the bottom

#### Locale Merge (Translatable Fields)

[](#locale-merge-translatable-fields)

For translatable/JSON columns, toggle the **Merge Translation** switch to split a field into multiple locale→column mappings:

```
Title (translatable)  →  Merge Translation ON
  [en] → title_en
  [ar] → title_ar
  [fr] → title_fr

```

The locale can be auto-detected from header names (`title_en`, `titleAr`, etc.) or entered manually. This stores data as JSON: `{"en": "Hello", "ar": "مرحبا"}`.

#### Relation Mapping

[](#relation-mapping)

For `BelongsTo` relations:

```
Category → [Select CSV column...]
           FK: category_id  PK: id
           [Search fields...]  [name ▼]

```

Relations support auto-increment ID detection (if CSV has numeric IDs) and intelligent fallback to string field matching.

### Step 3: Review &amp; Validate

[](#step-3-review--validate)

Preview your data before import:

- View first 100 rows with mapped columns
- See validation errors per row with error badges
- Dynamic rules auto-generated from database schema (column types, nullable, unique)
- Relation foreign keys bypass type constraints in validation (labels are resolved later)
- Configure upsert settings (enable/disable, keys)

### Step 4: Import

[](#step-4-import)

Start the import process:

- **Background queue processing** with live progress polling every 5 seconds
- **Sync queue** runs jobs immediately for testing
- **Eloquent mode** (non-upsert): Records are saved individually via `save()`, firing `boot()`, events, and observers
- **Upsert mode**: Bulk `upsert()` with fallback to chunked inserts on failure
- **Error tracking** with downloadable CSV error logs
- **Final summary** with animated success/error counts and `completed_with_errors` status

🔗 Relationship Linking
----------------------

[](#-relationship-linking)

Link related records during import:

```
// Example: Import products and link to categories
CSV Column: "Category Name" → Relation: category → Field: name
```

Supported relationship types:

- `BelongsTo` — with automatic FK/PK resolution

### How Relation Resolution Works

[](#how-relation-resolution-works)

1. If the owner key is an auto-incrementing primary key:
    - Numeric CSV values → find or create by ID
    - String CSV values → find or create by `name` field, or auto-detect a suitable string column
2. If the owner key is a non-ID column → direct lookup by that column
3. Translatable/locale-aware resolution via `whereJsonContains()` for JSON fields

🔃 Upsert (Match &amp; Merge)
----------------------------

[](#-upsert-match--merge)

Update existing records instead of creating duplicates:

```
ImportWizardAction::make()
    ->forModel(\App\Models\User::class)
    ->enableUpsert(true)
    ->upsertKeys(['email']);  // Match users by email
```

The wizard will:

1. Find existing records by the specified keys
2. Update matching records via `upsert()` (with timestamp injection)
3. Create new records only when no match is found
4. Fall back to chunked inserts on upsert failure

🌍 Spatie Translatable &amp; Locale Merge
----------------------------------------

[](#-spatie-translatable--locale-merge)

### Automatic Detection

[](#automatic-detection)

The wizard automatically detects:

- Models using `Spatie\Translatable\HasTranslations` trait
- JSON/JSONB columns from the database schema

### Locale Merge Mode

[](#locale-merge-mode)

Check **Merge Translation** on any translatable field to split it into locale-specific mappings:

CSV HeaderMaps To`title_en``title` with locale `en``title_ar``title` with locale `ar``title_fr``title` with locale `fr`The result is stored as a single JSON column: `{"en": "value", "ar": "قيمة", "fr": "valeur"}`

### Custom Import Field Labels

[](#custom-import-field-labels)

Add a `getImportFieldLabel()` method to your model for custom display names:

```
class Product extends Model
{
    public function getImportFieldLabel(string $field): string
    {
        return match($field) {
            'sku' => 'SKU (Stock Keeping Unit)',
            'price_in_cents' => 'Price (cents)',
            default => Str::title(str_replace(['_', '.'], ' ', $field)),
        };
    }
}
```

🧠 Smart Defaults &amp; Guarded Model Support
--------------------------------------------

[](#-smart-defaults--guarded-model-support)

The wizard handles models with `$guarded = []` (no fillable defined) gracefully:

- **Dynamic fillable resolution**: Falls back to `Schema::getColumnListing()` when `getFillable()` is empty
- **All columns allowed**: When fillable is empty, any CSV column can map to any database column
- **Foreign key resolution**: Bypasses fillable checks when model is fully unguarded

🛠️ Customization
----------------

[](#️-customization)

### Custom Modal Width

[](#custom-modal-width)

```
use Filament\Support\Enums\Width;

ImportWizardAction::make()
    ->forModel(\App\Models\Product::class)
    ->setModalWidth(Width::ExtraLarge);
```

### Queue Configuration

[](#queue-configuration)

Set queue connection and name globally via config:

```
// config/filament-import-wizard.php
return [
    'queue_connection' => 'redis',
    'queue_name' => 'imports',
];
```

Or per import action:

```
ImportWizardAction::make()
    ->forModel(\App\Models\Product::class)
    ->queueConnection('redis')
    ->queueName('imports');
```

### Custom Validation Rules

[](#custom-validation-rules)

Add a `getImportRules()` method to your model for custom import validation:

```
class Product extends Model
{
    public function getImportRules(): array
    {
        return [
            'sku' => ['required', 'string', 'max:50'],
            'price' => ['required', 'numeric', 'min:0'],
            'stock' => ['nullable', 'integer', 'min:0'],
        ];
    }
}
```

If no `getImportRules()` method exists, rules are auto-generated from the database schema.

📝 Requirements
--------------

[](#-requirements)

- **PHP**: 8.2+
- **Laravel**: 10+
- **Filament**: 4.x or 5.x

📄 License
---------

[](#-license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

🤝 Contributing
--------------

[](#-contributing)

Contributions are welcome! Please open an issue or submit a pull request.

📧 Support
---------

[](#-support)

If you discover any bugs or have feature requests, please open an issue on [GitHub](https://github.com/waad/filament-import-wizard/issues).

Screenshots
-----------

[](#screenshots)

[![Screenshot](screenshots/image1.png)](screenshots/image1.png)[![Screenshot](screenshots/image2.png)](screenshots/image2.png)[![Screenshot](screenshots/image3.png)](screenshots/image3.png)[![Screenshot](screenshots/image4.png)](screenshots/image4.png)

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance87

Actively maintained with recent releases

Popularity25

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~12 days

Total

4

Last Release

65d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/44348636?v=4)[Waad Mawlood](/maintainers/waadmawlood)[@waadmawlood](https://github.com/waadmawlood)

---

Top Contributors

[![waadmawlood](https://avatars.githubusercontent.com/u/44348636?v=4)](https://github.com/waadmawlood "waadmawlood (17 commits)")

---

Tags

excelcsvqueueimportmappinglivewirewizardfilamentrelationshipupsert

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/waad-filament-import-wizard/health.svg)

```
[![Health](https://phpackages.com/badges/waad-filament-import-wizard/health.svg)](https://phpackages.com/packages/waad-filament-import-wizard)
```

###  Alternatives

[yajra/laravel-datatables-export

Laravel DataTables Queued Export Plugin.

352.2M4](/packages/yajra-laravel-datatables-export)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

119.4k](/packages/tomshaw-electricgrid)[ercogx/laravel-filament-starter-kit

This is a Filament v5 Starter Kit for Laravel 13, designed to accelerate the development of Filament-powered applications.

461.8k](/packages/ercogx-laravel-filament-starter-kit)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
