filamentphp / advanced-import
Advanced Excel import functionality for Filament resources with preview, batch processing, and audit trail
Package info
github.com/anselmocossa/filamentphp-advanced-import
pkg:composer/filamentphp/advanced-import
Requires
- php: ^8.2
- filament/filament: ^4.0|^5.0
- maatwebsite/excel: ^3.1|^4.0
- spatie/laravel-package-tools: ^1.92
Requires (Dev)
- laravel/pint: ^1.0
- orchestra/testbench: ^9.0|^10.0|^11.0
- pestphp/pest: ^3.0|^4.0
README
Advanced Excel import functionality for Filament 4.x resources with preview, batch processing, and audit trail.
Features
- Excel Import with Preview - Load and preview Excel data before processing
- Batch Processing - Process imports in transactions with individual error tracking
- Audit Trail - Full import history with detailed logs for each record
- Customizable Processing - Define your own parsing and processing logic
- Multi-language Support - English and Portuguese translations included
- Artisan Commands - Quickly scaffold import pages and processors
- Filament 4.x & 5.x Ready - Built for Filament v4 and v5
Requirements
- PHP 8.2+
- Laravel 11+, 12+ or 13+
- Filament 4.0+ or 5.0+
- Maatwebsite Excel 3.1+ or 4.0+
Installation
Install the package via Composer:
composer require filamentphp/advanced-import
Run the install command:
php artisan import:install
This will:
- Publish the configuration file
- Publish and run the migrations
- Create the
importacoesandimportacao_detalhestables
Register the Plugin
Add the plugin to your Filament panel provider:
use Filament\AdvancedImport\AdvancedImportPlugin; public function panel(Panel $panel): Panel { return $panel // ... ->plugins([ AdvancedImportPlugin::make(), ]); }
Quick Start
1. Create an Import Page
Use the Artisan command to generate an import page:
php artisan import:page ClienteResource --model=Cliente
This creates app/Filament/Resources/Clientes/Pages/ImportClientes.php.
2. Create an Import Processor
Generate a processor for your import logic:
php artisan import:processor Clientes --category=clientes
This creates app/Processors/ImportClientesProcessor.php.
3. Customize the Import Page
Edit the generated page to define your columns and parsing:
<?php namespace App\Filament\Resources\Clientes\Pages; use App\Models\Cliente; use App\Processors\ImportClientesProcessor; use Filament\AdvancedImport\Contracts\ImportProcessor; use Filament\AdvancedImport\Pages\BaseImportPage; use Filament\Tables\Columns\TextColumn; class ImportClientes extends BaseImportPage { protected static string $resource = ClienteResource::class; protected static ?string $title = 'Importar Clientes'; protected function getImportProcessor(): ImportProcessor { return new ImportClientesProcessor(); } protected function parseRow(array $row): array { return [ 'nome' => $row['nome'] ?? $row['name'] ?? '', 'email' => $row['email'] ?? '', 'documento' => $row['numero_documento'] ?? $row['document'] ?? '', 'telefone' => $row['telefone'] ?? $row['phone'] ?? '', ]; } protected function getTableColumns(): array { return [ TextColumn::make('nome') ->label('Nome') ->searchable(), TextColumn::make('email') ->label('Email'), TextColumn::make('documento') ->label('Documento'), TextColumn::make('telefone') ->label('Telefone'), ]; } }
4. Customize the Processor
Edit the processor to handle your business logic:
<?php namespace App\Processors; use App\Models\Cliente; use Filament\AdvancedImport\Contracts\ImportProcessor; use Filament\AdvancedImport\Traits\ProcessesImport; class ImportClientesProcessor implements ImportProcessor { use ProcessesImport; public function process(array $dados, array $context = []): array { return $this->processImportBatch( dados: $dados, categoria: 'clientes', userId: auth()->id() ); } protected function processItem(array $item): array { // Validate required fields if (empty($item['email'])) { throw new \Exception('Email é obrigatório'); } // Create or update the record $cliente = Cliente::updateOrCreate( ['email' => $item['email']], [ 'nome' => $item['nome'], 'numero_documento' => $item['documento'], 'telefone' => $item['telefone'], ] ); return [ 'id' => $cliente->id, 'nome' => $cliente->nome, 'email' => $cliente->email, 'estado' => 'sucesso', ]; } }
5. Register the Page in Your Resource
Add the import page to your resource's pages:
public static function getPages(): array { return [ 'index' => Pages\ListClientes::route('/'), 'create' => Pages\CreateCliente::route('/create'), 'edit' => Pages\EditCliente::route('/{record}/edit'), 'import' => Pages\ImportClientes::route('/import'), ]; }
6. Add Navigation Link (Optional)
Add a link to the import page from your list page:
protected function getHeaderActions(): array { return [ Actions\CreateAction::make(), Actions\Action::make('import') ->label('Importar Excel') ->icon('heroicon-o-arrow-up-tray') ->url(fn () => static::getResource()::getUrl('import')), ]; }
Configuration
Publish the configuration file:
php artisan import:publish --config
Configuration Options
// config/advanced-import.php return [ // File upload settings 'file' => [ 'max_size' => 10240, // KB (10MB) 'disk' => 'public', 'directory' => 'imports', 'accepted_types' => [ 'application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ], ], // Available categories for imports 'categories' => [ 'clientes' => 'Clientes', 'contadores' => 'Contadores', 'contratos' => 'Contratos', // Add your custom categories ], // Database table names 'tables' => [ 'importacoes' => 'importacoes', 'importacao_detalhes' => 'importacao_detalhes', ], // Logging configuration 'logging' => [ 'channel' => null, // null = default Laravel channel 'log_success' => true, 'log_errors' => true, ], // Notification settings 'notifications' => [ 'show_success' => true, 'show_errors' => true, 'persistent' => true, ], ];
Advanced Usage
Custom Upload Form
Override the upload form schema in your import page:
protected function getUploadFormSchema(): array { return [ FileUpload::make('file') ->label(__('advanced-import::messages.form.file')) ->acceptedFileTypes($this->getAcceptedFileTypes()) ->maxSize($this->getMaxFileSize()) ->required(), Select::make('month') ->label('Mês de Referência') ->options([ 1 => 'Janeiro', 2 => 'Fevereiro', /* ... */ ]) ->required(), TextInput::make('year') ->label('Ano') ->numeric() ->default(now()->year) ->required(), ]; }
Context Data
Pass additional context to your processor:
protected function getProcessContext(): array { return [ 'month' => $this->data['month'] ?? null, 'year' => $this->data['year'] ?? null, 'imported_by' => auth()->user()->name, ]; }
Custom Number Parsing
Use the included NumberParser for handling different number formats:
use Filament\AdvancedImport\Support\NumberParser; protected function parseRow(array $row): array { return [ 'valor' => NumberParser::parse($row['valor']), // Handles "1.234,56" → 1234.56 'quantidade' => NumberParser::parseInt($row['qtd']), ]; }
Pre-Processing Validation
Add validation before processing starts:
protected function validateBeforeProcessing(): void { if (count($this->preview) > 1000) { throw new \Exception('Máximo de 1000 registos por importação'); } // Check for required columns $firstRow = $this->preview[0] ?? []; if (!isset($firstRow['email'])) { throw new \Exception('Coluna "email" não encontrada'); } }
Custom Result Columns
Show additional fields in the results table:
protected function getResultTableColumns(): array { return [ TextColumn::make('id') ->label('ID'), TextColumn::make('nome') ->label('Nome'), BadgeColumn::make('estado') ->colors([ 'success' => 'sucesso', 'danger' => 'falha', ]), TextColumn::make('erro') ->label('Erro') ->wrap() ->visible(fn ($record) => $record['estado'] === 'falha'), ]; }
Import Audit
The package includes a pre-built ImportacaoResource for viewing import history.
Features
- List all imports with filtering by category, date, and status
- View detailed import information
- See individual record results via RelationManager
- Read-only (no create/edit/delete operations)
Access
Navigate to System > Import History in your Filament panel.
Customizing the Audit Resource
If you need to customize the audit resource, publish and extend it:
php artisan import:publish --resources
Artisan Commands
import:install
Install the package (publish config, migrations, run migrations):
php artisan import:install
import:page
Create a new import page:
php artisan import:page ResourceName --model=ModelName
Options:
--model- The Eloquent model class name--force- Overwrite existing file
import:processor
Create a new import processor:
php artisan import:processor ProcessorName --category=category_name
Options:
--category- The import category for audit tracking--force- Overwrite existing file
import:publish
Publish package assets:
php artisan import:publish --config # Publish configuration php artisan import:publish --migrations # Publish migrations php artisan import:publish --views # Publish views php artisan import:publish --lang # Publish translations php artisan import:publish --stubs # Publish stubs php artisan import:publish --all # Publish everything
Translations
The package includes English and Portuguese translations. To customize:
php artisan import:publish --lang
This publishes to resources/lang/vendor/advanced-import/.
Adding New Languages
Create a new directory in resources/lang/vendor/advanced-import/ with your locale code and copy the messages.php file from an existing language.
Upgrading
From 1.x to 2.x
Run the upgrade migration:
php artisan migrate
Update your import pages to use the new ImportProcessor interface.
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.