avtonom/mathielen-import-engine
Installation
composer require mathielen/import-engine
Ensure ddeboer/data-import is also installed (dependency).
First Use Case: CSV Import
users.csv into a User model:
use Mathielen\ImportEngine\ImportEngine;
use Ddeboer\DataImport\Reader\CsvReader;
$reader = new CsvReader('path/to/users.csv');
$importEngine = new ImportEngine(new UserImportMapping());
$results = $importEngine->import($reader);
src/ImportEngine.php (core logic).src/Mapping/AbstractMapping.php (base mapping class).tests/ (real-world examples).Define a Mapping Class
Extend Mathielen\ImportEngine\Mapping\AbstractMapping and override:
getModel() → Return your Eloquent model class.getColumns() → Define CSV/array keys → model attributes.getRules() → Validation rules (e.g., ['email' => 'required|email']).class UserImportMapping extends AbstractMapping {
public function getModel() { return User::class; }
public function getColumns() {
return [
'email' => 'email',
'name' => 'name',
'role' => 'role_id',
];
}
public function getRules() {
return ['email' => 'required|unique:users'];
}
}
Handle Different Data Sources
CsvReader (default).League\Csv\ExcelReader (composer require league/csv).ArrayReader.
$reader = new ArrayReader(json_decode(file_get_contents('data.json'), true));
Batch Processing
Use ChunkReader to process large files in chunks:
$reader = new ChunkReader(new CsvReader('large_file.csv'), 100);
$importEngine->import($reader);
Post-Import Actions
ImportStarted, RowImported, ImportCompleted):
$importEngine->on('row.imported', function ($row) {
// Log or trigger side-effects (e.g., send welcome email).
});
Exporting Data Reuse mappings for exports:
$exporter = new ImportEngine(new UserImportMapping());
$exporter->export(User::all())->toCsv('users_export.csv');
AppServiceProvider:
$this->app->singleton(ImportEngine::class, function ($app) {
return new ImportEngine(new UserImportMapping());
});
class ImportUsersCommand extends Command {
protected $signature = 'import:users {file}';
public function handle() {
$engine = app(ImportEngine::class);
$results = $engine->import(new CsvReader($this->argument('file')));
$this->info("Imported {$results['imported']} users.");
}
}
dispatch(new ImportUsersJob('path/to/file.csv'));
class ImportUsersJob implements ShouldQueue {
public function handle() {
$engine = app(ImportEngine::class);
$engine->import(new CsvReader($this->filePath));
}
}
Column Mismatches
getColumns() keys.setHeaderRow() on the reader or override mapRow() in your mapping:
public function mapRow(array $row) {
return [
'email' => $row['Email'], // Case-sensitive!
'name' => $row['Full Name'],
];
}
Validation Errors
$importEngine->setLogger(new SingleLineLogger());
$results = $importEngine->import($reader);
dd($results['errors']); // Inspect failed rows.
Memory Limits
Allowed memory exhausted.ChunkReader or increase memory_limit in php.ini.Model Relationships
User with Address) require manual handling.afterImport to resolve relationships:
public function afterImport() {
User::with('address')->find($this->getImportedIds())->get();
}
$importEngine->setLogger(new StreamHandler(storage_path('logs/import.log'), Logger::DEBUG));
Custom Readers
Implement Ddeboer\DataImport\Reader\ReaderInterface for unsupported formats (e.g., XML):
class XmlReader implements ReaderInterface {
public function getRecords() { /* ... */ }
}
Pre/Post-Processing
Override beforeImport() or afterImport() in your mapping:
public function beforeImport() {
DB::beginTransaction();
}
public function afterImport() {
DB::commit();
}
Custom Error Handling
Extend Mathielen\ImportEngine\ImportEngine to modify error responses:
class CustomImportEngine extends ImportEngine {
protected function handleRowErrors(array $errors) {
// Custom logic (e.g., notify admin).
}
}
Database Transactions Wrap imports in transactions for data integrity:
DB::transaction(function () use ($engine, $reader) {
$engine->import($reader);
});
config/app.php timezone matches your import data to avoid timestamp issues.setLocale() on the reader for date/number parsing:
$reader->setLocale('de_DE');
How can I help you explore Laravel packages today?