elcodi-plugins/product-csv
Elcodi Product CSV plugin adds CSV import/export support for product data in Elcodi e-commerce applications. Part of the MIT-licensed Elcodi suite built on Symfony; this repository is read-only, with issues and contributions handled via elcodi/bamboo.
Read this before you install anything. elcodi-plugins/product-csv is part of the archived Elcodi suite (EOL, last release 2016-02-15, read-only repository, zero dependents). It targets the Symfony 2.x / PHP 5.x era. Treat it as a reference implementation you might vendor into a legacy codebase, not as a live dependency you add to a modern project.
Minimal steps if you are working inside an existing Elcodi application:
dev-master — the README's "use last unstable version" advice is actively harmful here, because the branch is frozen and unreviewed:
composer require elcodi-plugins/product-csv:"~1.0" --no-update
If Composer refuses to resolve (likely on PHP 7.4+), clone the repo into src/ or a packages/ path repository instead.app/AppKernel.php alongside the Elcodi core bundles it depends on (ProductBundle, and whatever attribute/media bundles your product model uses). Order matters — register it after the product bundle.Resources/config/services.yml (or .xml) — this is the real documentation. It gives you the service IDs for the reader/writer/importer/exporter and their constructor arguments.Command/ — any elcodi:product:*csv* console commands, which are the fastest way to a first successful run.Tests/ — fixture CSV files live here and double as the de facto schema spec for column names, delimiters, and quoting.product, product_variant, and product_prices before you touch real data.If you do not already run Elcodi, stop here. The package is not worth standing up an EOL Symfony 2 stack for; read the source and lift the ~200 lines of CSV mapping logic instead.
Import as a seeding step, not as a recurring workflow. The plugin predates robust queuing and idempotency conventions. The realistic pattern is: use it to bootstrap a catalog into a dev/staging environment, then move to a purpose-built importer for production. Keep the call site isolated behind your own service so a future replacement is a one-line swap:
// Your own boundary service — do not let controllers call the plugin directly.
final class CatalogCsvSeeder
{
public function __construct(private ProductCsvImporter $importer) {}
public function seed(string $path): ImportReport
{
return $this->importer->import($path); // wrap, log, count, do not leak the plugin type
}
}
Round-trip export → spreadsheet edit → re-import. The strongest day-to-day use of a CSV plugin is merchandising: export the current catalog, let a category manager edit prices and descriptions in Excel, re-import. For this to work you must confirm the exporter's column set is a superset of the importer's accepted headers — often it is not, and you will need a small mapping layer between the two.
Key on SKU for idempotency. Assume the plugin's default behavior is "create," not "upsert." Wrap the import so it resolves an existing product by SKU first and updates it, otherwise a second run duplicates your entire catalog. Verify this against your data before trusting repeated runs.
Chunk large files yourself. Read the CSV in batches (a few hundred rows), clear the Doctrine entity manager between batches, and wrap each batch in its own transaction. This is the single change that turns an import that exhausts memory into one that completes.
Drive it from a console command or cron entry. In Elcodi's era the intended entry point is a Symfony command. Put the CSV path, delimiter, and "dry run" flag in the command signature so operators can validate without writing:
app/console elcodi:product:csv:import catalog.csv --dry-run
Validate before you persist. Parse the whole row into a DTO, assert required columns and price parseability, collect row-numbered errors, and only then hand anything to the importer. The plugin's error reporting is minimal; a per-row error CSV keyed by line number is worth the twenty minutes it takes to build.
composer why-not and a static analysis pass before assuming it loads. Budget for a rewrite, not a patch.services.yml and the tests over documentation.; as a delimiter in many locales. Strip the BOM on the first header cell or your first column becomes \xEF\xBB\xBFsku and silently fails to match. Set the delimiter explicitly rather than relying on a default.fgetcsv semantics) and not a naive explode(','). Test with a description containing " and a newline.1.234,56) will parse as garbage. Normalize to a decimal string with . before import, and verify the currency is applied from config rather than the CSV.app/config/config.yml under an elcodi_* key. If the importer ignores your delimiter, the bundle is probably not reading the parameter you set — check the bundle's DependencyInjection/Configuration.php.How can I help you explore Laravel packages today?