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

Wilbercsv Laravel Package

wilber/wilbercsv

Wilber CSV is a lightweight Laravel package for working with CSV files, making it easy to import and export tabular data. Configure delimiters, headers, and column mapping, then integrate CSV handling into your models and workflows with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Confirm you can actually install it. The composer name is wilber/wilbercsv but the repository is tyshantprince/laracsv — that mismatch plus 0 stars, 0 dependents and a last release from June 2017 means Packagist may not serve it. Try:

composer require wilber/wilbercsv

If that fails, add a VCS repository entry in composer.json and require it as dev-master. Either way, pin the constraint and commit composer.lock; there will be no patch releases.

2. Check the Laravel version ceiling first. A 2017 package targets Laravel 5.4/5.5. On 5.5+ the service provider and CSV facade are auto-discovered via extra.laravel. On anything older (or if auto-discovery is missing) add to config/app.php:

'providers' => [Wilber\WilberCsv\CsvServiceProvider::class],
'aliases'   => ['CSV' => Wilber\WilberCsv\Facades\Csv::class],

On Laravel 9/10/11 expect composer require to resolve but the provider to blow up on $defer, boot() signatures or facade getFacadeAccessor() returning a string that no longer binds. Budget an hour to read src/ before promising the feature to anyone.

3. Look here first. In the repo, read in this order: composer.json (constraints, autoload namespace), src/ for the provider/facade, then the README examples. The API is the classic laracsv shape:

CSV::create('users.csv', function ($csv, $model) {
    $csv->addRow(['id' => $model->id, 'email' => $model->email]);
});

4. First use case — an admin "Export users" button. A route returning a streamed download of the users table is the smallest thing that proves the package works end to end in your app:

Route::get('/admin/users/export', function () {
    return CSV::from(User::query()->get())
        ->setHeaders(['ID', 'Name', 'Email'])
        ->get();
});

If that downloads a valid file, the rest is refinement.

Implementation Patterns

Stream, don't collect. The core value of this package over fputcsv by hand is that it writes row-by-row to php://output rather than building a giant string. Feed it lazily so you don't defeat that:

return CSV::from(User::query()->cursor())
    ->setHeaders(['ID', 'Name', 'Email'])
    ->get();

For anything over ~50k rows, prefer chunkById with a manual fputcsv loop over a php://output handle — you keep control of memory and get the same result.

Encapsulate one exporter class per report. Don't scatter CSV::from(...) calls through controllers. A small class with headers(), query() and map($row) keeps column definitions in one place and makes the package swappable later:

class UserCsvExporter
{
    public function query() { return User::query()->with('team'); }
    public function headers(): array { return ['ID', 'Name', 'Team', 'Created']; }
    public function map(User $u): array {
        return [$u->id, $u->name, $u->team?->name, $u->created_at->toDateString()];
    }
}

Eager-load every relation you touch. Accessors that hit the DB per row turn a 10-second export into a timeout. with() on the query passed to the exporter is mandatory, not optional.

Split "generate" from "deliver". For scheduled or large exports, write to disk and hand out a signed URL instead of streaming in the request:

Storage::put('exports/users-'.now()->timestamp.'.csv', $csv->toString());

Wrap it in a queued job and notify the user when the file is ready — this survives PHP max_execution_time and reverse-proxy buffering.

Use it for imports' sibling tasks. The same header/mapping vocabulary you build for exports is the natural place to define the canonical column set that your CSV imports validate against, so the round trip stays symmetric.

Test with Storage::fake. Assert on the written file contents rather than on response headers — file assertions are stable across Laravel versions and catch column-ordering regressions.

Gotchas and Tips

It is effectively abandoned. Last release June 2017, one release, zero dependents. Treat it as vendored code you own: fork it into app/Support or a private package rather than depending on the upstream. The functionality is ~100 lines; reimplementing it on top of league/csv (actively maintained) or maatwebsite/excel costs less than a Laravel upgrade debugging session.

PHP 8 and Laravel 9+ compatibility is unverified. Expect dynamic-property deprecations, missing return types, and facade binding changes. Run php -l and a smoke test in CI the moment you bump the framework.

Excel formula injection. Any cell starting with =, +, -, @, tab or CR is executed by Excel. Prefix with a single quote or a tab for user-supplied strings (names, comments, addresses). The package will not do this for you.

UTF-8 for Excel. Excel on Windows mangles non-ASCII unless you emit a UTF-8 BOM (\xEF\xBB\xBF) before the first header row. Conversely, a stray BOM or a whitespace character before <?php in any loaded file will corrupt the download or trigger "headers already sent" — the classic streaming-export failure.

Locale delimiters. fputcsv uses ,; German/French Excel expects ;. If the finance team opens the file, add a delimiter option or post-process.

Attributes vs. raw values. $model->created_at is a Carbon instance and casts/mutators apply — decide explicitly whether you want toDateTimeString(), ISO-8601, or the raw DB string. Accessors that were designed for Blade (getFullNameAttribute) are usually what you want here; $model->getAttributes() is what you want when you need the untransformed columns.

Hidden/guarded fields leak. Iterating $model->toArray() will ship password hashes and API tokens. Always enumerate columns explicitly.

Headers before output. Return the streamed response and let the framework set Content-Type: text/csv and Content-Disposition; never echo anything in the controller, and beware debug middleware (laravel-debugbar, dd, a stray dump) injecting output into the stream.

Extension points. If you keep the package, subclass the generator or bind your own implementation to the facade accessor so you can add BOM handling, sanitisation and delimiter config in one place instead of at every call site. That single wrapper is also your migration path to league/csv — swap the internals, keep the call sites.

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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings