Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Batch Entity Import Bundle Laravel Package

jgrygierek/batch-entity-import-bundle

A Symfony bundle for importing large sets of Doctrine entities in batches from files, with configurable field mapping and validation to keep memory use low and imports reliable.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: despite the framing, jgrygierek/batch-entity-import-bundle is a Symfony bundle, not a Laravel package. It ships no service provider, no facade, and no config/ publish tag. It expects Symfony's DI container, Doctrine ORM entities, and (typically) Twig templates for the preview/edit UI. If you're on Laravel, you cannot composer require it into an app and expect it to boot — you either use it inside a Symfony service in a polyglot setup, or you read its source as a reference implementation and rebuild the same flow with maatwebsite/excel + a staging table + Filament/Livewire.

Assuming a Symfony context:

  1. composer require jgrygierek/batch-entity-import-bundle — Flex should register it in config/bundles.php automatically; otherwise add it manually.
  2. Read the README's example entity first, then look at src/ for the importer service and the attribute/annotation directory — that's where column mapping, required flags, and transformers are declared.
  3. Check tests/ for the canonical end-to-end usage; with a package this small (12 stars, 0 dependents) the tests are the most reliable documentation of the actual API surface.
  4. First use case: bulk-create entities from a CSV/XLSX where a human must review and correct rows before they hit the database — that preview-then-commit loop is the entire value proposition versus a naive fgetcsv + flush() loop.

The canonical wiring is a two-route flow: POST /import/upload parses the file into transient entity objects and renders them in an editable table; POST /import/confirm takes the (possibly edited) rows and persists them.

Implementation Patterns

Upload → preview → edit → commit. Treat the preview step as the contract. Keep parsed rows in the session (or a temporary table for large files), re-validate on confirm, and persist only what the user approved. Never let the upload endpoint write to the DB directly.

Declare the schema on the entity, not in the controller. The bundle's model is to annotate/attribute the Doctrine entity's properties with column metadata (header name, required, transformer, validator constraints). This keeps the import definition next to the field it describes and lets the same config drive both parsing and preview rendering.

// Illustrative shape — confirm exact attribute names in src/
#[Importable(header: 'sku', required: true)]
private string $sku;

#[Importable(header: 'price', transformer: PriceTransformer::class)]
private int $priceCents;

Reuse the Symfony Validator. The preview objects are just entity instances, so $validator->validate($entity) works unchanged. Surface errors on the preview row so the user fixes them in place rather than re-uploading.

Resolve relations by natural key, with a cache. For ManyToOne columns (category name, supplier code), pre-load a lookup map once per request ($repo->createQueryBuilder()->indexBy(...)) rather than querying per row. This is the single biggest performance lever on a 10k-row file.

Batch the flush. EntityManager::flush() per row will crawl. persist() everything, flush() + clear() every 100–500 rows, and wrap the confirm step in a transaction so a mid-file failure doesn't leave half-imported data.

Laravel-side equivalent if you're porting the pattern: a POST /imports that stores the file and creates an import_batches row, an import_rows staging table with status (pending/valid/invalid/committed), a Livewire or Filament table for the edit step, and a queued job that maps staging rows onto Eloquent models inside DB::transaction(). The bundle's two-phase design maps cleanly onto this.

Gotchas and Tips

  • Symfony-only, and it knows it. It assumes Doctrine's UnitOfWork, Symfony Form/Validator, and Twig. Don't try to bridge it into Laravel via a custom container shim; the coupling is deeper than a service provider.
  • Bus-factor risk is real. 12 stars, 0 dependents, one maintainer. Vendor it (composer require with a pinned version, or fork) and be prepared to own the code. Read src/ end-to-end before building on it — it's small enough to audit in an afternoon.
  • Release date looks off. The listed last release (2026-10-17) is in the future relative to typical package metadata; verify against the actual tags/CHANGELOG on GitHub before assuming a stable API. Pin to a commit SHA if the tag history is unclear.
  • CSV header matching is brittle. Header case, whitespace, and UTF-8 BOM (\xEF\xBB\xBF) are the usual first-day bugs. Strip the BOM, trim() headers, and normalize before matching against your declared import keys.
  • Session-stored preview state doesn't scale. Fine for a few hundred rows; for thousands, either raise limits knowingly or move preview rows into a temp/staging table. Session serialization of full entity graphs also drags along Doctrine proxies — store scalars, rehydrate on confirm.
  • Identity map blowup. With a long-running import, Doctrine accumulates managed entities until clear(). If you clear(), remember your relation lookup cache of managed entities goes stale — cache IDs or use getReference().
  • Duplicate rows within the same file won't be caught by a unique constraint check until flush, because the first row isn't committed yet. Validate intra-file uniqueness in the preview step explicitly.
  • Extension points to reach for: custom transformers for value coercion (dates, decimals, enums), custom constraint classes for domain rules, and template overrides for the preview table. These are safer than forking core logic.
  • Debugging: dump the parsed row set before validation (that's where column mapping errors surface), and log validation failures per row with the source line number. With no dependents and sparse docs, a var_dump at the parse boundary will outpace guessing from the README.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo