Export an Eloquent Collection to a CSV with League CSV
!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