Export an Eloquent Collection to a CSV with League CSV

Posted on March 2, 2015

!
Warning: This post is over a year old. I don't always update old posts with new information, so some of this information may be out of date.

League/CSV is a wonderfully simple wrapper around PHP's native CSV support, and it's simple to dump your Laravel Eloquent collection results out to CSV.

There's a ton more you can do with CSV, so go check out the docs, but here's a simple recipe to get started:

1. Install CSV

$ composer require league/csv

2. Prep the data

Let's say you're in an export method in your controller.

public function export()
{
    $people = Person::all();
}

3. Create the CSV file in memory

$csv = \League\Csv\Writer::createFromFileObject(new \SplTempFileObject);

4. Create your headers

You can manually pass an array of your headers, but this is the quick you can get it up and running in a prototype:

$csv->insertOne(array_keys($people[0]->getAttributes()));

You just inserted a row (insertOne()) filled with an array of the column names from your people table.

Thanks to Steve Barbera on Twitter for pointing out that the code I originally had here would fail in many settings.

5. Insert your rows

foreach ($people as $person) {
    $csv->insertOne($person->toArray());
}

6. Output it to the user

$csv->output('people.csv');

That's it! ... sort of. If you use the CSV writer's output() method, it'll write directly to the browser, which is fine in some contexts. But in Laravel, you're really better off creating a Laravel response object and setting your headers manually and then adding the CSV output to that response object, like this:

return response((string) $writer, 200, [
    'Content-Type' => 'text/csv',
    'Content-Transfer-Encoding' => 'binary',
    'Content-Disposition' => 'attachment; filename="people.csv"',
]);

Conclusion

Now, that's really it! You're now dumping an entire Eloquent collection result straight to CSV. Let's check it out:

public function export()
{
    $people = Person::all();

    $csv = \League\Csv\Writer::createFromFileObject(new \SplTempFileObject);

    $csv->insertOne(array_keys($people[0]->getAttributes()));

    foreach ($people as $person) {
        $csv->insertOne($person->toArray());
    }

    return response((string) $writer, 200, [
        'Content-Type' => 'text/csv',
        'Content-Transfer-Encoding' => 'binary',
        'Content-Disposition' => 'attachment; filename="people.csv"',
    ]);
}

If someone visits that route, they'll get people.csv downloaded straight into their browser. Done.

Again, check the docs to learn more about it. I hope this helps!


Comments? I'm @stauffermatt on Twitter


Tags: laravel  •  csv

Subscribe

Quick links to fresh content, and more thoughts that don't make it to the blog