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

Csv Bundle Laravel Package

kuborgh/csv-bundle

Kuborgh CSV Bundle integrates CSV handling into Symfony applications, providing configurable services for reading, writing, and processing CSV files. It simplifies import/export tasks and keeps CSV logic reusable across your project.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire up (slightly less friction than before).

  1. composer require kuborgh/csv-bundle:^1.0 — the v1.0.1 tag gives you a clean semver constraint, so you should no longer need "minimum-stability" overrides or pin a dev-master reference. If Composer still complains, check the release's composer adaptation for the PHP constraint it declares; fall back to pinning the exact tag.
  2. Register the bundle the old way: add new Kuborgh\CsvBundle\CsvBundle() to AppKernel::registerBundles() (Symfony 2/3) or to config/bundles.php (Symfony 4+, if you're lucky enough that it loads — see Gotchas).
  3. Dump the container (bin/console debug:container | grep -i csv) and confirm the service ID. The bundle ships a DI extension that registers a converter service; treat the exact ID as something to discover, not assume, since there's no maintained docs.

Where to look first. In priority order:

  • Resources/config/services.yml — tells you the real service ID and constructor args (delimiter, enclosure, encoding are usually injected here).
  • The converter class itself (something like CsvConverter / Csv) — that's your real API surface. Read the public methods before writing any integration code; the readme (if present) is often stale relative to the code.
  • DependencyInjection/CsvExtension.php — confirms what's configurable via config.yml.

First use case — a quick smoke test in a controller:

$converter = $this->get('kuborgh_csv.converter'); // verify ID first

// array -> CSV string
$csv = $converter->arrayToCsv([
    ['id' => 1, 'name' => 'Alice'],
    ['id' => 2, 'name' => 'Bob'],
]);

// CSV string -> array
$rows = $converter->csvToArray($csv);

Run that before anything else. If both directions round-trip a couple of rows, the package is doing its one job and you can build on it.

Implementation Patterns

Export endpoints (array → CSV). The natural fit is an admin "download report" action. Build your rows as associative arrays, let the converter emit the CSV string, then return a Response with Content-Type: text/csv and a Content-Disposition: attachment header:

public function exportAction()
{
    $rows = $this->getDoctrine()->getRepository(User::class)->findAllAsArray();
    $csv  = $this->get('kuborgh_csv.converter')->arrayToCsv($rows);

    $response = new Response($csv);
    $response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
    $response->headers->set('Content-Disposition', 'attachment; filename="users.csv"');
    return $response;
}

Keep the mapping (entity → plain array) in a separate service so the CSV library stays an implementation detail you can swap out later.

Import flows (CSV → array). Handle the uploaded file with Symfony's UploadedFile, read the contents, hand the string to csvToArray, then validate/normalise rows before persisting. Because the package just converts, all header mapping, type casting, and deduplication is on you:

$contents = file_get_contents($file->getPathname());
$rows = $converter->csvToArray($contents);

// First row is usually headers — decide explicitly whether to strip it
$headers = array_shift($rows);
$mapped  = array_map(fn($r) => array_combine($headers, $r), $rows);

Wire it as a service, not a global grab. Inject the converter into your own import/export services via constructor argument (service ID from debug:container). This keeps controllers thin and makes the eventual migration to league/csv a one-line constructor change.

Console commands. Both directions work well inside a Command: read a file, csvToArray, process, arrayToCsv, write out. Because the converter is stateless, you can loop over many files in one command invocation without re-instantiating.

Config-driven formatting. If the bundle's extension exposes delimiter/enclosure/encoding, set them once in config.yml rather than hardcoding — especially encoding, since Excel users will otherwise complain about mojibake on accented characters.

Test harness. Since there are no dependents and no active maintenance, write a small integration test that round-trips your real data shapes (nested values, missing keys, commas-in-quotes, newlines-in-quotes). That test becomes your regression suite if you ever replace the package.

Gotchas and Tips

  • v1.0.1 is a packaging release, not a revival. The notes are explicit: no code changes, only Composer and Travis adaptation. You get the same 2016 converter code, wrapped in a valid semver tag. Treat it as unmaintained code you're adopting — the ^1.0 constraint is nicer than a commit hash, but the maintenance posture hasn't changed. Note a fork-or-replace plan in your README; league/csv remains the safer default for anything long-lived.
  • The Travis/composer adaptation changes what's declared testable, not what's proven. Updated CI config can imply the maintainer ran the suite against newer PHP/Symfony, but with zero code diffs, any compatibility gain is environmental only. Don't read the version bump as "PHP 8 support confirmed" — verify yourself.
  • Symfony version compatibility is still the first wall. A 2016 bundle targets Symfony 2.x/3.x conventions (bundle class, AppKernel, Resources/config/services.yml, possibly services.yml without autowiring). On Symfony 4+ this often still loads but won't autowire — you may need to declare services manually or use a compiler pass. Budget time for this before promising a feature.
  • PHP version drift. Expect PHP 5.x-era code (no strict types, array() syntax in places, possibly deprecated calls). On PHP 8+ this can throw deprecations or fatals; run php -l against the vendor files and check your error log after first use. The Composer adaptation may have relaxed the PHP requirement constraint in composer.json, which means Composer will install it on newer runtimes — that's permission, not evidence it runs cleanly.
  • Encoding and BOM. Excel loves a UTF-8 BOM; the converter almost certainly won't add one. Prepend "\xEF\xBB\xBF" yourself on export, and strip it on import before parsing, or your first header will be \xEF\xBB\xBFid.
  • Delimiter/quotes are the classic failure. Commas and newlines inside quoted fields are where naive CSV libraries break. Verify round-tripping of values like "Smith, John" and multi-line addresses. If the converter doesn't handle them, sanitise or reject those inputs explicitly.
  • Memory and streaming. These converters typically build the whole string in memory. Fine for a few thousand rows; a problem for large exports. For big datasets, batch the query and write incrementally to php://output, or switch to a streaming writer.
  • No header semantics. The package converts raw rows; it doesn't know or care about headers, dtypes, or nulls. All of that business logic is yours — keep it in dedicated mappers, not inline in the controller.
  • Debugging. When output looks wrong, var_dump the raw array before conversion and the string after — the bug is almost always in the array shape (nested arrays, missing keys) rather than the converter. Enable debug:container output to confirm you're actually hitting the bundle's service and not a similarly-named one.
  • Extension points. The cleanest escape hatch is to subclass the converter and re-register it under the same service ID (or a new one) in your app config, overriding delimiter/encoding behaviour without forking. If you need real features, fork the repo into vendor under your namespace and treat it as your own code — with 0 dependents, nobody else will maintain it for you.
  • Licence is friendly. MIT means forking is legally trivial. That's your fallback when the 2016 code finally breaks against a newer Symfony/PHP — which it eventually will.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core