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

Import Laravel Package

lephare/import

LePhare Import is a Laravel package that streamlines importing structured data from CSV and Excel files into Eloquent models. It provides configurable column mappings, row validation, value transformation, chunked processing, and queued import jobs in a clean, extensible workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small, low-adoption package (6 stars, 0 dependents), so treat the source as the documentation — read src/ before wiring it into anything critical. The payoff is a thin, Laravel-native layer over CSV/XLS reading that saves you from hand-rolling fgetcsv loops and PhpSpreadsheet plumbing. The v2.4.4 changelog also confirms a feature the old assessment only guessed at: the package manages a quarantine directory and rotates it, meaning files move through configured disks/directories rather than being read from an arbitrary path.

Minimal path:

  1. Install — composer require lephare/import. Laravel package discovery should register the service provider; confirm with php artisan about or by checking vendor/lephare/import/composer.json for an extra.laravel block.
  2. Publish config — php artisan vendor:publish --tag=import-config. Look specifically for the disk/path settings behind the import and quarantine directories — those are the knobs the DirectoryNotFoundException fix touches.
  3. Scaffold an import — look for an artisan generator (make:import) in src/Console. If none exists, extend the package's base import class directly and define your columns there.
  4. Pick your first target — a customers.csv with name,email,company is the right size. Define the expected headers, attach a Validator ruleset, and map each row to a Customer model.
  5. Run it — through the provided command or by instantiating the import class and pointing it at a path on a configured disk. Verify where the file lands afterwards (quarantine vs. archive) before you build a scheduled job around it.

Where to look first, in order: the base import class (the hooks you override), any Importable/Row contract, the config file (directories, disks, rotation), then tests/ — the package's own fixtures show the exact expected file shapes faster than any README.

Implementation Patterns

One import class per file shape. Don't build a generic "any CSV" importer. Each source (Stripe export, client spreadsheet, legacy ERP dump) gets its own class with its own header map and validation. This is the single biggest maintainability win with any CSV package, and it's what the class-per-import design pushes你 toward.

Header mapping, not positional columns. Bind source headers to attribute names explicitly. Client spreadsheets reorder columns without warning; positional $row[2] breaks silently, named lookup throws or skips.

Validate before you cast. Run Laravel's Validator against the raw string values, then cast. 'amount' => 'required|numeric' on the raw cell catches "1.234,56" before (float) turns it into 1.234. Collect failures per row with the source line number rather than aborting the whole file.

Upsert on a natural key. For repeat imports, updateOrCreate on email/SKU/external_id. This makes re-runs idempotent and turns "the client sent the file again" from an incident into a no-op.

Lean on the quarantine directory for operations, not just cleanup. Since the package owns a quarantine directory and rotates it, treat it as your audit trail: quarantined files are the ones that failed or are awaiting review, and the rotation is what keeps that directory from growing forever. Point it at a dedicated disk (S3 prefix or a local storage/app/imports/quarantine), and make sure your own scheduled commands that list/archive from it tolerate the directory being recreated mid-run.

Chunk + queue for anything past ~5k rows. Read in batches, dispatch a job per chunk, accumulate a per-import status record (processed / failed / errors). The import class itself should stay synchronous and testable; the queue orchestration lives in a wrapper job. Watch your worker timeout — a chunk of 500 with per-row DB writes is usually the sweet spot.

Failed-row reporting is the feature. Persist row_number, the raw row, and the validation message to an import_errors table or a JSON column. Then give the user a re-upload of just the failed rows. This is what separates a usable importer from a demo.

Test with fixture files, not mocks. Put real .csv samples in tests/Fixtures/, point the import at Storage::fake('local'), assert final model counts and error counts. Also assert the post-run file location — with directory rotation in play, a Storage::fake disk gives you a cheap way to prove the file moved where you expect instead of blowing up.

Integration tip — schedule it. Pull files from S3/SFTP in a scheduled command, import, then let the package's rotation/archive handling move the processed file. Idempotent upserts make overlapping schedules safe.

Gotchas and Tips

Quarantine rotation needs the directory to exist and be writable. v2.4.4 fixes a DirectoryNotFoundException thrown during quarantine directory rotation (#43), so if you use this feature, pin >= 2.4.4 and verify permissions on the configured disk — a missing parent directory or a read-only mount is the classic trigger. If you're on 2.4.3 or below, you'll hit this on the first rotation after a prune.

Memory is the default killer. If the API returns a collection of all rows, a 200MB XLS will OOM you. Confirm the reader streams or chunks; if it doesn't, pass a row limit and loop, or switch the input to CSV.

Excel date serials. XLS/XLSX dates arrive as integers (45292), not strings. If the package doesn't normalize them, you'll write 1970-era dates to the DB and only notice in the UI. Verify how date columns come through before trusting Carbon::parse.

Encoding and BOM. A UTF-8 BOM (\xEF\xBB\xBF) prefixes the first header, so 'email' never matches and every row fails validation on a column that looks fine. Windows-1252 exports (very common from French/European Excel) mangle accents. Detect and convert before parsing.

Delimiter and locale. Excel in European locales exports ;-delimited CSV and numbers as 1 234,56. Auto-detection is unreliable; make the delimiter configurable per import class and document the expected format for whoever sends the file.

Empty string vs null. A blank cell may come through as '', null, or the string 'NULL'. Normalize at the mapping layer, or your nullable rules and unique indexes will behave inconsistently.

Transaction scope. Wrap per chunk, not per file. A 50k-row file in one transaction locks tables for the duration and rolls back everything on row 49,999.

Queue retries duplicate work. If a chunk job partially succeeds then times out, a retry re-runs the already-processed rows. Upserts make this harmless; plain create() does not. Never disable retries without also making the write idempotent.

Row numbers drift. Decide once whether your error reports are 1-indexed with the header counted. Off-by-one in error reporting means users fix the wrong line.

Pin the version. With 6 stars and no dependents, the API is not stabilized by production use elsewhere. Use an exact-ish constraint ("lephare/import": "2.4.*", minimum 2.4.4 if you rely on quarantine rotation) and read the diff before upgrading — a minor bump may rename a base-class hook.

Extension points to check in source: the row-mapping method (override for computed fields), the validator hook (override to inject context like the authenticated tenant), the directory/quarantine configuration, and any beforeImport/afterImport callbacks for cache warming or notification. If a hook you need doesn't exist, subclassing the base import class is usually cleaner than forking.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle