chriskelemba / excel-import
Framework-agnostic CSV/XLSX/JSON import package for PHP
Package info
github.com/chriskelemba/excel-import
Type:yii2-extension
pkg:composer/chriskelemba/excel-import
Requires (Dev)
- yiisoft/yii2: ^2.0.45
- yiisoft/yii2-composer: ^2.0
Suggests
- ext-pdo_mysql: Required for MySQL/MariaDB connections.
- ext-pdo_pgsql: Required for PostgreSQL connections.
- ext-pdo_sqlite: Required for SQLite connections.
- ext-pdo_sqlsrv: Required for SQL Server connections.
- mongodb/mongodb: Required for MongoDB support.
- phpoffice/phpspreadsheet: Required for XLSX support.
- yiisoft/yii2: Required for Yii route-only usage.
- yiisoft/yii2-composer: Required to auto-register the package Yii bootstrap/controller map.
README
Standalone CSV/XLSX/JSON/NDJSON preview + import engine for PHP.
This is the same core functionality as excel-import-laravel, extracted so it can run in:
- plain PHP projects
- Laravel (service/controller wrapper in app code)
- Yii (service/controller wrapper in app code)
Install
composer require chriskelemba/excel-import
Optional:
composer require phpoffice/phpspreadsheet # XLSX support composer require mongodb/mongodb # MongoDB support
Database Support
Supported through PDO adapters:
- MySQL / MariaDB (
pdo_mysql) - PostgreSQL (
pdo_pgsql) - SQLite (
pdo_sqlite) - SQL Server (
pdo_sqlsrv)
Supported through Mongo adapter:
- MongoDB (
mongodb/mongodbpackage)
Notes:
- Register one or many connections and switch by
connectionparameter in service calls. insertandupsertmodes work across the supported SQL drivers and MongoDB.- Column/type discovery is automatic for SQL tables.
- MongoDB is schema-less; columns are inferred from sampled documents unless overridden in config.
Quick Start (Plain PHP + PDO)
<?php use ChrisKelemba\ExcelImport\DynamicImporter; $pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', 'secret'); $importer = (new DynamicImporter(config: [ 'connection' => 'mysql', 'discovery' => [ 'allow_unconfigured_tables' => true, 'allow_tables' => [], 'exclude_tables' => ['migrations'], ], 'tables' => [ 'skills' => [ 'required' => ['name'], 'unique_by' => ['name'], 'mode' => 'upsert', ], ], ])) ->addPdoConnection('mysql', $pdo) ->service(); $preview = $importer->preview( filePath: __DIR__ . '/skills.xlsx', originalName: 'skills.xlsx', table: 'skills', columnMap: ['Skill Name' => 'name'], staticValues: ['ctg_id' => 2] ); $result = $importer->run( filePath: __DIR__ . '/skills.xlsx', originalName: 'skills.xlsx', table: 'skills', columnMap: ['Skill Name' => 'name'], mode: 'upsert', uniqueBy: ['name'] );
PostgreSQL Example
<?php use ChrisKelemba\ExcelImport\DynamicImporter; $pdo = new PDO('pgsql:host=127.0.0.1;port=5432;dbname=test', 'postgres', 'secret'); $service = (new DynamicImporter(config: ['connection' => 'pgsql'])) ->addPdoConnection('pgsql', $pdo) ->service();
MongoDB Connection
$mongo = new MongoDB\Client('mongodb://127.0.0.1:27017'); $service = (new DynamicImporter(config: ['connection' => 'mongodb'])) ->addMongoConnection('mongodb', $mongo, 'my_database') ->service();
Public Service API
template(?string $table = null, ?string $connection = null): arraydatabases(?string $connection = null, ?string $table = null): arrayrecords(string $table, ?string $connection = null, int $page = 1, int $perPage = 25): arraypreview(string $filePath, string $originalName, string $table, array $columnMap = [], array $staticValues = [], ?int $headerRow = null, int $sampleRows = 10, int $sheetIndex = 0, ?string $connection = null): arrayrun(string $filePath, string $originalName, string $table, array $columnMap, array $staticValues = [], ?int $headerRow = null, ?string $mode = null, array $uniqueBy = [], int $sheetIndex = 0, ?string $connection = null): arrayrunMulti(string $filePath, string $originalName, array $imports, ?string $connection = null): array
Behavior Parity Notes
- Same file readers: CSV/TXT, XLSX, JSON/NDJSON
- Same header detection, auto-mapping, validation, sample mapping, and import modes (
insert/upsert) - Same static values support and numeric/date normalization
- Same multi-table import flow (
runMulti) - Same Mongo schema inference behavior (top-level keys sampled from documents)
Laravel/Yii Usage
Wrap this package inside your framework controller/service:
- Convert uploaded file to
filePath+originalName - Pass request payload into
preview,run, orrunMulti - Return JSON response in your framework format
No framework dependency is required by this package.
Route-Only Integration (No Custom Controller Logic)
If you want consumers to only define routes, use the HTTP actions bridge:
<?php use ChrisKelemba\ExcelImport\DynamicImporter; $actions = (new DynamicImporter())->http();
In Laravel, if no connection is manually registered, DynamicImporter auto-resolves the framework DB connection (from config('database.default') / .env) and uses it.
Then bind routes directly:
// Laravel Route::get('/imports/template', [$actions, 'template']); Route::get('/imports/databases', [$actions, 'databases']); Route::get('/imports/records', [$actions, 'records']); Route::post('/imports/preview', [$actions, 'preview']); Route::post('/imports/run', [$actions, 'run']);
// Yii // No custom app controller needed. // Package auto-registers `imports` controller in Yii via bootstrap. 'rules' => [ 'GET imports/template' => 'imports/template', 'GET imports/databases' => 'imports/databases', 'GET imports/records' => 'imports/records', 'POST imports/preview' => 'imports/preview', 'POST imports/run' => 'imports/run', ];
// Plain PHP (any router) $actions = /* build as above */; $result = $actions->run(); // reads body/query/files from globals when request is omitted
Payload/file handling supported by the bridge:
imports(array or JSON string), or single-import payload withtablefileupload from request/$_FILES, or explicitfile_path+ optionaloriginal_name
Minimal Consumer Workflow
For minimal controller code, use the workflow helper:
<?php use ChrisKelemba\ExcelImport\DynamicImporter; $workflow = (new DynamicImporter(config: ['connection' => 'mysql'])) ->addPdoConnection('mysql', $pdo) ->workflow(); $preview = $workflow->previewFromPayload( filePath: $filePath, originalName: $originalName, payload: $requestPayload // array or JSON string with `imports` ); $result = $workflow->runFromPayload( filePath: $filePath, originalName: $originalName, payload: $requestPayload // array or JSON string with `imports` );
imports supports snake_case and camelCase keys:
column_map/columnMapstatic_values/staticValuesheader_row/headerRowsample_rows/sampleRowsunique_by/uniqueBysheet_index/sheetIndex